package io.synor.hosting;

import java.util.List;
import java.util.Map;

/**
 * Hosting SDK Types for Java.
 */
public class Types {
    // Organizational class
}

// ==================== Config ====================

class HostingConfig {
    private final String apiKey;
    private final String endpoint;
    private final int timeoutSecs;
    private final int retries;
    private final boolean debug;

    public HostingConfig(String apiKey) {
        this(apiKey, "https://hosting.synor.io/v1", 60, 3, false);
    }

    public HostingConfig(String apiKey, String endpoint, int timeoutSecs, int retries, boolean debug) {
        this.apiKey = apiKey;
        this.endpoint = endpoint;
        this.timeoutSecs = timeoutSecs;
        this.retries = retries;
        this.debug = debug;
    }

    public String getApiKey() { return apiKey; }
    public String getEndpoint() { return endpoint; }
    public int getTimeoutSecs() { return timeoutSecs; }
    public int getRetries() { return retries; }
    public boolean isDebug() { return debug; }
}

// ==================== Domain Types ====================

enum DomainStatus { pending, active, expired, suspended }

class Domain {
    private String name;
    private DomainStatus status;
    private String owner;
    private long registeredAt;
    private long expiresAt;
    private boolean autoRenew;
    private DomainRecord records;

    public String getName() { return name; }
    public DomainStatus getStatus() { return status; }
    public String getOwner() { return owner; }
    public long getRegisteredAt() { return registeredAt; }
    public long getExpiresAt() { return expiresAt; }
    public boolean isAutoRenew() { return autoRenew; }
    public DomainRecord getRecords() { return records; }
}

class DomainRecord {
    private String cid;
    private List<String> ipv4;
    private List<String> ipv6;
    private String cname;
    private List<String> txt;
    private Map<String, String> metadata;

    public String getCid() { return cid; }
    public List<String> getIpv4() { return ipv4; }
    public List<String> getIpv6() { return ipv6; }
    public String getCname() { return cname; }
    public List<String> getTxt() { return txt; }
    public Map<String, String> getMetadata() { return metadata; }

    public void setCid(String cid) { this.cid = cid; }
    public void setIpv4(List<String> ipv4) { this.ipv4 = ipv4; }
    public void setIpv6(List<String> ipv6) { this.ipv6 = ipv6; }
    public void setCname(String cname) { this.cname = cname; }
    public void setTxt(List<String> txt) { this.txt = txt; }
    public void setMetadata(Map<String, String> metadata) { this.metadata = metadata; }
}

class DomainAvailability {
    private String name;
    private boolean available;
    private Double price;
    private boolean premium;

    public String getName() { return name; }
    public boolean isAvailable() { return available; }
    public Double getPrice() { return price; }
    public boolean isPremium() { return premium; }
}

class RegisterDomainOptions {
    private Integer years;
    private Boolean autoRenew;

    public Integer getYears() { return years; }
    public Boolean getAutoRenew() { return autoRenew; }
    public void setYears(Integer years) { this.years = years; }
    public void setAutoRenew(Boolean autoRenew) { this.autoRenew = autoRenew; }
}

// ==================== DNS Types ====================

enum DnsRecordType { A, AAAA, CNAME, TXT, MX, NS, SRV, CAA }

class DnsRecord {
    private DnsRecordType type;
    private String name;
    private String value;
    private int ttl = 3600;
    private Integer priority;

    public DnsRecordType getType() { return type; }
    public String getName() { return name; }
    public String getValue() { return value; }
    public int getTtl() { return ttl; }
    public Integer getPriority() { return priority; }

    public void setType(DnsRecordType type) { this.type = type; }
    public void setName(String name) { this.name = name; }
    public void setValue(String value) { this.value = value; }
    public void setTtl(int ttl) { this.ttl = ttl; }
    public void setPriority(Integer priority) { this.priority = priority; }
}

class DnsZone {
    private String domain;
    private List<DnsRecord> records;
    private long updatedAt;

    public String getDomain() { return domain; }
    public List<DnsRecord> getRecords() { return records; }
    public long getUpdatedAt() { return updatedAt; }
}

// ==================== Deployment Types ====================

enum DeploymentStatus { pending, building, deploying, active, failed, inactive }

class Deployment {
    private String id;
    private String domain;
    private String cid;
    private DeploymentStatus status;
    private String url;
    private long createdAt;
    private long updatedAt;
    private String buildLogs;
    private String errorMessage;

    public String getId() { return id; }
    public String getDomain() { return domain; }
    public String getCid() { return cid; }
    public DeploymentStatus getStatus() { return status; }
    public String getUrl() { return url; }
    public long getCreatedAt() { return createdAt; }
    public long getUpdatedAt() { return updatedAt; }
    public String getBuildLogs() { return buildLogs; }
    public String getErrorMessage() { return errorMessage; }
}

class DeployOptions {
    private String domain;
    private String subdomain;
    private Boolean spa;
    private Boolean cleanUrls;
    private Boolean trailingSlash;

    public String getDomain() { return domain; }
    public String getSubdomain() { return subdomain; }
    public Boolean getSpa() { return spa; }
    public Boolean getCleanUrls() { return cleanUrls; }
    public Boolean getTrailingSlash() { return trailingSlash; }

    public void setDomain(String domain) { this.domain = domain; }
    public void setSubdomain(String subdomain) { this.subdomain = subdomain; }
    public void setSpa(Boolean spa) { this.spa = spa; }
    public void setCleanUrls(Boolean cleanUrls) { this.cleanUrls = cleanUrls; }
    public void setTrailingSlash(Boolean trailingSlash) { this.trailingSlash = trailingSlash; }
}

// ==================== SSL Types ====================

enum CertificateStatus { pending, issued, expired, revoked }

class Certificate {
    private String domain;
    private CertificateStatus status;
    private boolean autoRenew;
    private String issuer;
    private Long issuedAt;
    private Long expiresAt;
    private String fingerprint;

    public String getDomain() { return domain; }
    public CertificateStatus getStatus() { return status; }
    public boolean isAutoRenew() { return autoRenew; }
    public String getIssuer() { return issuer; }
    public Long getIssuedAt() { return issuedAt; }
    public Long getExpiresAt() { return expiresAt; }
    public String getFingerprint() { return fingerprint; }
}

class ProvisionSslOptions {
    private Boolean includeWww;
    private Boolean autoRenew;

    public Boolean getIncludeWww() { return includeWww; }
    public Boolean getAutoRenew() { return autoRenew; }
    public void setIncludeWww(Boolean includeWww) { this.includeWww = includeWww; }
    public void setAutoRenew(Boolean autoRenew) { this.autoRenew = autoRenew; }
}

// ==================== Site Config ====================

class SiteConfig {
    private String domain;
    private String cid;
    private Map<String, String> headers;
    private List<RedirectRule> redirects;
    private Map<String, String> errorPages;
    private boolean spa;
    private boolean cleanUrls;
    private boolean trailingSlash;

    public String getDomain() { return domain; }
    public String getCid() { return cid; }
    public Map<String, String> getHeaders() { return headers; }
    public List<RedirectRule> getRedirects() { return redirects; }
    public Map<String, String> getErrorPages() { return errorPages; }
    public boolean isSpa() { return spa; }
    public boolean isCleanUrls() { return cleanUrls; }
    public boolean isTrailingSlash() { return trailingSlash; }
}

class RedirectRule {
    private String source;
    private String destination;
    private int statusCode = 301;
    private boolean permanent = true;

    public String getSource() { return source; }
    public String getDestination() { return destination; }
    public int getStatusCode() { return statusCode; }
    public boolean isPermanent() { return permanent; }
}

// ==================== Analytics ====================

class AnalyticsData {
    private String domain;
    private String period;
    private long pageViews;
    private long uniqueVisitors;
    private long bandwidth;
    private List<PageView> topPages;
    private List<Referrer> topReferrers;
    private List<Country> topCountries;

    public String getDomain() { return domain; }
    public String getPeriod() { return period; }
    public long getPageViews() { return pageViews; }
    public long getUniqueVisitors() { return uniqueVisitors; }
    public long getBandwidth() { return bandwidth; }
    public List<PageView> getTopPages() { return topPages; }
    public List<Referrer> getTopReferrers() { return topReferrers; }
    public List<Country> getTopCountries() { return topCountries; }
}

class PageView {
    private String path;
    private long views;
    public String getPath() { return path; }
    public long getViews() { return views; }
}

class Referrer {
    private String referrer;
    private long count;
    public String getReferrer() { return referrer; }
    public long getCount() { return count; }
}

class Country {
    private String country;
    private long count;
    public String getCountry() { return country; }
    public long getCount() { return count; }
}

class AnalyticsOptions {
    private String period;
    private String start;
    private String end;

    public String getPeriod() { return period; }
    public String getStart() { return start; }
    public String getEnd() { return end; }
    public void setPeriod(String period) { this.period = period; }
    public void setStart(String start) { this.start = start; }
    public void setEnd(String end) { this.end = end; }
}

// ==================== Error ====================

class HostingException extends RuntimeException {
    private final String code;
    private final int statusCode;

    public HostingException(String message) {
        super(message);
        this.code = null;
        this.statusCode = 0;
    }

    public HostingException(String message, String code, int statusCode) {
        super(message);
        this.code = code;
        this.statusCode = statusCode;
    }

    public String getCode() { return code; }
    public int getStatusCode() { return statusCode; }
}
