package com.atlassian.bitbucket.internal.mirroring;

import com.atlassian.bitbucket.user.ApplicationUser;
import com.google.common.base.MoreObjects;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.net.URI;
import java.util.Date;

import static com.google.common.base.Preconditions.checkNotNull;

public class SimpleMirroringRequest implements MirroringRequest {

    private final URI addonDescriptorUri;
    private final Date createdDate;
    private final Integer id;
    private final String mirrorBaseUrl;
    private final String mirrorName;
    private final String mirrorId;
    private final String productType;
    private final String productVersion;
    private final MirroringRequestState state;

    private SimpleMirroringRequest(Builder builder) {
        id = builder.id;
        addonDescriptorUri = checkNotNull(builder.addonDescriptorUri, "addonDescriptorUri");
        mirrorBaseUrl = checkNotNull(builder.mirrorBaseUrl, "mirrorBaseUrl");
        createdDate = checkNotNull(builder.createdDate, "createdDate");
        mirrorName = checkNotNull(builder.mirrorName, "mirrorName");
        mirrorId = checkNotNull(builder.mirrorId, "mirrorId");
        productType = checkNotNull(builder.productType, "productType");
        productVersion = checkNotNull(builder.productVersion, "productVersion");
        state = checkNotNull(builder.state, "state");
    }

    @Nonnull
    @Override
    public URI getAddonDescriptorUri() {
        return addonDescriptorUri;
    }

    @Nonnull
    @Override
    public Date getCreatedDate() {
        return new Date(createdDate.getTime());
    }

    @Nonnull
    @Override
    public Integer getId() {
        return id;
    }

    @Nonnull
    @Override
    public String getBaseUrl() {
        return mirrorBaseUrl;
    }

    @Nonnull
    @Override
    public String getMirrorId() {
        return mirrorId;
    }

    @Nonnull
    @Override
    public String getMirrorName() {
        return mirrorName;
    }

    @Nonnull
    @Override
    public String getProductType() {
        return productType;
    }

    @Nonnull
    @Override
    public String getProductVersion() {
        return productVersion;
    }

    @Nullable
    @Override
    public Date getResolvedDate() {
        return null;
    }

    @Nullable
    @Override
    public ApplicationUser getResolver() {
        return null;
    }

    @Nonnull
    @Override
    public MirroringRequestState getState() {
        return state;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("addonDescriptorUri", addonDescriptorUri)
                .add("createdDate", createdDate)
                .add("id", id)
                .add("mirrorBaseUrl", mirrorBaseUrl)
                .add("mirrorName", mirrorName)
                .add("mirrorId", mirrorId)
                .add("productType", productType)
                .add("productVersion", productVersion)
                .add("state", state)
                .add("baseUrl", getBaseUrl())
                .add("resolvedDate", getResolvedDate())
                .add("resolver", getResolver())
                .toString();
    }

    public static class Builder {
        private Integer id;
        private URI addonDescriptorUri;
        private Date createdDate = new Date();
        private String mirrorBaseUrl;
        private String mirrorId;
        private String mirrorName;
        private String productType;
        private String productVersion;
        private MirroringRequestState state = MirroringRequestState.PENDING;

        @Nonnull
        public Builder addonDescriptor(@Nonnull URI value) {
            addonDescriptorUri = checkNotNull(value, "addonDescriptor");
            return this;
        }

        @Nonnull
        public Builder mirrorBaseUrl(@Nonnull String value) {
            mirrorBaseUrl = value;
            return this;
        }

        @Nonnull
        public SimpleMirroringRequest build() {
            return new SimpleMirroringRequest(this);
        }

        @Nonnull
        public Builder createdDate(@Nonnull Date value) {
            createdDate = new Date(checkNotNull(value, "createdDate").getTime());
            return this;
        }

        @Nonnull
        public Builder id(@Nullable Integer id) {
            this.id = id;
            return this;
        }

        @Nonnull
        public Builder mirrorServer(@Nonnull String id, @Nonnull String name) {
            mirrorId = checkNotNull(id, "mirrorId");
            mirrorName = checkNotNull(name, "mirrorName");
            return this;
        }

        @Nonnull
        public Builder product(@Nonnull String type, @Nonnull String version) {
            productType = checkNotNull(type, "productType");
            productVersion = checkNotNull(version, "productVersion");
            return this;
        }

        @Nonnull
        public Builder state(@Nonnull MirroringRequestState state) {
            this.state = checkNotNull(state, "state");
            return this;
        }
    }
}
