package com.atlassian.bitbucket.internal.mirroring.mirror;

import com.atlassian.bitbucket.mirroring.mirror.MirroredRepository;
import com.atlassian.bitbucket.mirroring.mirror.MirroredRepositoryStatus;
import com.atlassian.bitbucket.util.NamedLink;
import com.google.common.collect.ImmutableSet;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Date;
import java.util.Optional;
import java.util.Set;

import static java.util.Objects.requireNonNull;

public class SimpleMirroredRepository implements MirroredRepository {

    private final Set<NamedLink> cloneUrls;
    private final Optional<Date> lastUpdated;
    private final String mirrorName;
    private final String repositoryId;
    private final MirroredRepositoryStatus status;

    private SimpleMirroredRepository(Builder builder) {
        status = requireNonNull(builder.status, "status");
        cloneUrls = builder.cloneUrls.build();
        lastUpdated = builder.lastUpdated == null ? Optional.<Date>empty() : Optional.of(builder.lastUpdated);
        mirrorName = requireNonNull(builder.mirrorName, "mirrorName");
        repositoryId = requireNonNull(builder.repositoryId, "repositoryId");
    }

    @Nonnull
    @Override
    public Set<NamedLink> getCloneUrls() {
        return cloneUrls;
    }

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

    @Nonnull
    @Override
    public Optional<Date> getLastUpdated() {
        return lastUpdated;
    }

    @Nonnull
    @Override
    public String getRepositoryId() {
        return repositoryId;
    }

    @Override
    public boolean isAvailable() {
        return status == MirroredRepositoryStatus.AVAILABLE
                || status == MirroredRepositoryStatus.ERROR_AVAILABLE;
    }

    @Nonnull
    @Override
    public MirroredRepositoryStatus getStatus() {
        return status;
    }

    public static class Builder {

        private final ImmutableSet.Builder<NamedLink> cloneUrls;
        private Date lastUpdated;
        private String mirrorName;
        private String repositoryId;
        private MirroredRepositoryStatus status;

        public Builder() {
            cloneUrls = ImmutableSet.builder();
        }

        public Builder status(@Nonnull MirroredRepositoryStatus value) {
            requireNonNull(value, "status");
            status = value;
            return this;
        }

        public Builder cloneUrl(@Nonnull NamedLink value) {
            requireNonNull(value, "cloneUrl");
            cloneUrls.add(value);
            return this;
        }

        public Builder cloneUrls(@Nonnull Iterable<NamedLink> value) {
            requireNonNull(value, "cloneUrls");
            cloneUrls.addAll(value);
            return this;
        }

        public Builder lastUpdated(@Nullable Date value) {
            lastUpdated = value;
            return this;
        }

        public Builder mirrorName(@Nonnull String value) {
            requireNonNull(value, "mirrorName");
            mirrorName = value;
            return this;
        }

        public Builder repositoryId(@Nonnull String value) {
            requireNonNull(value, "repositoryId");
            repositoryId = value;
            return this;
        }

        public SimpleMirroredRepository build() {
            return new SimpleMirroredRepository(this);
        }
    }
}
