package com.atlassian.bitbucket.internal.importer.repository;

import com.atlassian.bitbucket.internal.importer.dao.AoRepositoryImportTask;
import com.atlassian.bitbucket.internal.importer.dao.ImporterDao;
import com.atlassian.bitbucket.internal.importer.event.RepositoryImportTaskStateChangedEvent;
import com.atlassian.event.api.EventPublisher;
import org.springframework.beans.factory.annotation.Qualifier;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class RepositoryImportTaskHelper {

    private final EventPublisher eventPublisher;
    private final ImporterDao importerDao;

    public RepositoryImportTaskHelper(@Qualifier("eventPublisher") @Nonnull EventPublisher eventPublisher,
                                      @Qualifier("importerDao") @Nonnull ImporterDao importerDao) {
        this.eventPublisher = eventPublisher;
        this.importerDao = importerDao;
    }

    public void failImportTask(long taskId, @Nonnull ImportTaskFailureType failureType) {
        AoRepositoryImportTask importTaskStarted = importerDao.updateImportTaskState(taskId, ImportTaskState.FAILED, failureType);
        publishEvent(importTaskStarted);
    }

    public void updateImportTask(long taskId, @Nonnull ImportTaskState state) {
        if (state == ImportTaskState.FAILED) {
            throw new IllegalArgumentException("To update a FAILED task, or set a task to FAILED, call failImportTask instead");
        }
        AoRepositoryImportTask importTaskStarted = importerDao.updateImportTaskState(taskId, state, null);
        publishEvent(importTaskStarted);
    }

    public AoRepositoryImportTask createFailedImportTask(long jobId,
                                                         @Nonnull String cloneUrl,
                                                         @Nonnull String externalRepoName,
                                                         int repositoryId,
                                                         @Nonnull ImportTaskFailureType failureType) {
        return createImportTask(jobId, cloneUrl, externalRepoName, repositoryId, ImportTaskState.FAILED, failureType);
    }

    public AoRepositoryImportTask createImportTask(long jobId,
                                                   @Nonnull String cloneUrl,
                                                   @Nonnull String externalRepoName,
                                                   int repositoryId,
                                                   @Nonnull ImportTaskState state) {
        if (state == ImportTaskState.FAILED) {
            throw new IllegalArgumentException("To create a FAILED task, call createFailedTask instead");
        }
        return createImportTask(jobId, cloneUrl, externalRepoName, repositoryId, state, null);
    }

    private AoRepositoryImportTask createImportTask(long jobId,
                                                    @Nonnull String cloneUrl,
                                                    @Nonnull String externalRepoName,
                                                    int repositoryId,
                                                    @Nonnull ImportTaskState state,
                                                    @Nullable ImportTaskFailureType failureType) {
        AoRepositoryImportTask importTask = importerDao.createImportTask(jobId, cloneUrl, externalRepoName, failureType, repositoryId,
                state);
        publishEvent(importTask);
        return importTask;
    }

    private void publishEvent(AoRepositoryImportTask aoRepositoryImportTask) {
        eventPublisher.publish(new RepositoryImportTaskStateChangedEvent(this,
                aoRepositoryImportTask.getState(),
                aoRepositoryImportTask.getFailureType(),
                aoRepositoryImportTask.getImportJobId(),
                aoRepositoryImportTask.getRepositoryId(),
                aoRepositoryImportTask.getId()));
    }
}
