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

import com.atlassian.bitbucket.i18n.I18nService;
import com.atlassian.bitbucket.internal.mirroring.mirror.MirroringConfig;
import com.atlassian.bitbucket.internal.mirroring.mirror.jwt.JwtSignedRequestFactory;
import com.atlassian.bitbucket.internal.mirroring.mirror.nav.MirroringNavBuilder;
import com.atlassian.bitbucket.internal.mirroring.ssh.encoding.PublicKeyEncodingHelper;
import com.atlassian.bitbucket.json.JsonRenderer;
import com.atlassian.bitbucket.mirroring.mirror.UpstreamServer;
import com.atlassian.bitbucket.server.ApplicationPropertiesService;
import com.atlassian.httpclient.api.HttpClient;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Nonnull;
import javax.validation.Validator;

import static com.atlassian.bitbucket.internal.mirroring.mirror.MirrorDescriptionUtils.describe;
import static com.atlassian.bitbucket.mirroring.mirror.UpstreamServerType.BITBUCKET_CLOUD;
import static com.atlassian.bitbucket.mirroring.mirror.UpstreamServerType.BITBUCKET_SERVER;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

public class DefaultUpstreamClientFactory implements InternalUpstreamClientFactory {

    private final MirroringConfig config;
    private final HttpClient httpClient;
    private final I18nService i18nService;
    private final JsonRenderer jsonRenderer;
    private final JwtSignedRequestFactory jwtSignedRequestFactory;
    private final MirroringNavBuilder mirroringNavBuilder;
    private final ApplicationPropertiesService propertiesService;
    private final PublicKeyEncodingHelper publicKeyHelper;
    private final Validator validator;

    @Autowired
    public DefaultUpstreamClientFactory(MirroringConfig config, HttpClient httpClient, I18nService i18nService,
                                        JsonRenderer jsonRenderer, JwtSignedRequestFactory jwtSignedRequestFactory,
                                        MirroringNavBuilder mirroringNavBuilder,
                                        ApplicationPropertiesService propertiesService,
                                        PublicKeyEncodingHelper publicKeyHelper, Validator validator) {
        this.config = config;
        this.httpClient = httpClient;
        this.i18nService = i18nService;
        this.jsonRenderer = jsonRenderer;
        this.jwtSignedRequestFactory = jwtSignedRequestFactory;
        this.mirroringNavBuilder = mirroringNavBuilder;
        this.propertiesService = propertiesService;
        this.publicKeyHelper = publicKeyHelper;
        this.validator = validator;
    }

    @Nonnull
    @Override
    public InternalUpstreamClient create(@Nonnull UpstreamServer upstream) {
        switch (checkNotNull(upstream, "upstream").getType()) {
            case BITBUCKET_CLOUD:
                return createForCloud(upstream);
            case BITBUCKET_SERVER:
                return createForServer(upstream);
            default:
                throw new IllegalArgumentException(String.format("Upstream %s is of an unexpected type", describe(upstream)));
        }
    }

    @Nonnull
    @Override
    public CloudUpstreamClient createForCloud(@Nonnull UpstreamServer upstream) {
        checkNotNull(upstream, "upstream");
        checkArgument(upstream.getType() == BITBUCKET_CLOUD, "Upstream %s must be of type %s", describe(upstream), BITBUCKET_CLOUD);
        return new DefaultCloudUpstreamClient(config, httpClient, i18nService, jsonRenderer,
                mirroringNavBuilder, jwtSignedRequestFactory, upstream, validator);
    }

    @Nonnull
    @Override
    public ServerUpstreamClient createForServer(@Nonnull UpstreamServer upstream) {
        checkNotNull(upstream, "upstream");
        checkArgument(upstream.getType() == BITBUCKET_SERVER, "Upstream %s must be of type %s", describe(upstream), BITBUCKET_SERVER);
        return new DefaultServerUpstreamClient(config, httpClient, i18nService, jsonRenderer, mirroringNavBuilder,
                publicKeyHelper, propertiesService, jwtSignedRequestFactory, upstream, validator);
    }
}
