package com.armstrongconsulting.acprotasks;

import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import com.armstrongconsulting.acprotasks.client.AcproConnector;
import com.armstrongconsulting.acprotasks.client.model.ItemsContainer;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.tasks.Task;
import com.intellij.tasks.TaskRepositoryType;
import com.intellij.tasks.impl.BaseRepository;
import com.intellij.util.xmlb.annotations.Tag;

import feign.FeignException;
import lombok.extern.slf4j.Slf4j;

@Tag(AcproRepositoryType.NAME)
@Slf4j
public class AcproRepository extends BaseRepository
{
    public AcproRepository(TaskRepositoryType type)
    {
        super(type);
    }

    public AcproRepository(AcproRepository other)
    {
        super(other);
        setRepositoryType(other.getRepositoryType());
        setApiKey(other.getApiKey());
    }

    public AcproRepository()
    {
    }

    @Override
    public @Nullable Task findTask(@NotNull String id) throws Exception
    {
        return null;
    }

    @Override
    public @NotNull BaseRepository clone()
    {
        return new AcproRepository(this);
    }

    @Override
    public Task[] getIssues(@Nullable String query, int offset, int limit, boolean withClosed,
        @NotNull ProgressIndicator cancelled) throws Exception
    {
        if (StringUtils.isBlank(query))
        {
            return new Task[0];
        }

        ItemsContainer response = AcproConnector.getClient(this).getItems(query, offset, limit);
        Task[] result = new Task[0];
        if (response.getItems() != null && response.getItems().getItem() != null)
        {
            result = response.getItems().getItem().stream().map(AcproTask::new).toArray(Task[]::new);
        }
        return result;
    }

    private final AcproRepository self = this;

    @Override
    public @Nullable CancellableConnection createCancellableConnection()
    {
        return new CancellableConnection()
        {
            @Override
            protected void doTest() throws Exception
            {
                // do login and set apiKey
                try
                {
                    setApiKey(
                        AcproConnector.getClient(self).getApiKey(getUsername(), getPassword()));
                    log.warn("Fetched api key: {}", getApiKey());
                }
                catch (FeignException.Unauthorized e)
                {
                    throw new RuntimeException("Failed to authenticate", e);
                }
                catch (FeignException e)
                {
                    throw new RuntimeException("Failed to connect to server", e);
                }
            }

            @Override
            public void cancel()
            {
                // not cancellable
            }
        };
    }

    public String getApiKey()
    {
        return PropertiesComponent.getInstance().getValue("api_key");
    }

    public void setApiKey(String apiKey)
    {
        PropertiesComponent.getInstance().setValue("api_key", apiKey);
    }
}
