package dp.kotul.bamboospecsapplication.creator;

import com.atlassian.bamboo.specs.api.builders.task.Task;
import com.atlassian.bamboo.specs.builders.task.ArtifactDownloaderTask;
import com.atlassian.bamboo.specs.builders.task.ArtifactItem;
import com.atlassian.bamboo.specs.builders.task.CleanWorkingDirectoryTask;
import com.atlassian.bamboo.specs.builders.task.DockerBuildImageTask;
import com.atlassian.bamboo.specs.builders.task.DockerPullImageTask;
import com.atlassian.bamboo.specs.builders.task.DockerPushImageTask;
import com.atlassian.bamboo.specs.builders.task.DownloadItem;
import com.atlassian.bamboo.specs.builders.task.ScpTask;
import com.atlassian.bamboo.specs.builders.task.ScriptTask;
import com.atlassian.bamboo.specs.builders.task.SshTask;
import com.atlassian.bamboo.specs.builders.task.VcsCheckoutTask;
import dp.kotul.bamboospecsapplication.EnvironmentEnum;
import dp.kotul.bamboospecsapplication.configuration.DeploymentTaskConfiguration;
import dp.kotul.bamboospecsapplication.util.BambooUtils;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.List;

public class DeploymentTaskCreator {
    private DeploymentTaskCreator(){}

    private static EnvironmentEnum environment;

    public static Task[] createDeploymentTasks(List<DeploymentTaskConfiguration> tasksFromConfig, EnvironmentEnum environmentEnum) {
        environment = environmentEnum;
        List<Task> tasks = new ArrayList<>();
        tasks.add(new CleanWorkingDirectoryTask());
        for (DeploymentTaskConfiguration task : tasksFromConfig) {
            tasks.add(createTask(task));
        }
        return tasks.stream().toArray(Task[]::new);
    }

    private static Task createTask(DeploymentTaskConfiguration taskConfig) {
        switch (taskConfig.getType()) {
            case SCRIPT: return createScriptTask(taskConfig);
            case SSH: return createSshTask(taskConfig);
            case SCP: return createScpTask(taskConfig);
            case SOURCE_CHECKOUT: return createSourceCheckoutTask(taskConfig);
            case ARTIFACT_DOWNLOAD: return createArtifactDownloadTask(taskConfig);
            case DOCKER_IMAGE_BUILD: return createDockerImageBuildTask(taskConfig);
            case DOCKER_IMAGE_PUSH: return createDockerImagePushTask(taskConfig);
            case DOCKER_IMAGE_PULL: return createDockerPullTask(taskConfig);
            default: throw new InvalidParameterException(taskConfig.getType() + " type is not supported");
        }
    }

    private static Task createScriptTask(DeploymentTaskConfiguration taskConfig) {
        ScriptTask scriptTask = new ScriptTask()
                .description(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getDescription(), environment))
                .interpreterBinSh()
                .inlineBody(BambooUtils.replaceEnvPlaceholderWithEnvironment(String.join("\n", taskConfig.getContent()), environment));

        if (taskConfig.getEnvironmentVariables() != null) {
            scriptTask.environmentVariables(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getEnvironmentVariables(), environment));
        }

        return scriptTask;
    }

    private static Task createSshTask(DeploymentTaskConfiguration taskConfig) {
        return new SshTask()
                .description(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getDescription(), environment))
                .host(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getHost(), environment))
                .username(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getUsername(), environment))
                .authenticateWithPassword(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getPassword(), environment))
                .command(BambooUtils.replaceEnvPlaceholderWithEnvironment(String.join("\n", taskConfig.getContent()), environment));
    }

    private static Task createScpTask(DeploymentTaskConfiguration taskConfig) {

        return new ScpTask()
                .description(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getDescription(), environment))
                .host(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getHost(), environment))
                .username(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getUsername(), environment))
                .authenticateWithPassword(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getPassword(), environment))
                .fromArtifact(new ArtifactItem().artifact(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getArtifactName(), environment)))
                .toRemotePath(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getRemotePath(), environment));
    }

    private static Task createSourceCheckoutTask(DeploymentTaskConfiguration taskConfig) {
        return new VcsCheckoutTask()
                .description(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getDescription(), environment))
                .addCheckoutOfRepository(taskConfig.getRepositoryName());
    }

    private static Task createArtifactDownloadTask(DeploymentTaskConfiguration taskConfig) {
        ArtifactDownloaderTask task = new ArtifactDownloaderTask()
                .description(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getDescription(), environment));

        if (taskConfig.getArtifactName() == null) {
            task.artifacts(new DownloadItem().allArtifacts(true));
        } else {
            task.artifacts(new DownloadItem().artifact(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getArtifactName(), environment)));
        }

        return task;
    }

    private static Task createDockerImageBuildTask(DeploymentTaskConfiguration taskConfig) {
        return new DockerBuildImageTask()
                .description(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getDescription(), environment))
                .dockerfileInWorkingDir()
                .useCache(true)
                .imageName(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getImageName(), environment));
    }

    private static Task createDockerImagePushTask(DeploymentTaskConfiguration taskConfig) {
        return new DockerPushImageTask()
                .description(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getDescription(), environment))
                .customRegistryImage(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getImageName(), environment))
                .authentication(taskConfig.getUsername(), BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getPassword(), environment));
    }

    private static Task createDockerPullTask(DeploymentTaskConfiguration taskConfig) {
        return new DockerPullImageTask()
                .description(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getDescription(), environment))
                .customRegistryImage(BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getImageName(), environment))
                .authentication(taskConfig.getUsername(), BambooUtils.replaceEnvPlaceholderWithEnvironment(taskConfig.getPassword(), environment));
    }
}
