package com.atlassian.bitbucket.internal.integration.jira.idx;

import com.atlassian.bitbucket.integration.jira.JiraConstants;
import com.atlassian.integration.jira.JiraKeyScanner;
import com.atlassian.bitbucket.commit.Commit;
import com.atlassian.bitbucket.idx.CommitIndex;
import com.atlassian.bitbucket.idx.CommitIndexer;
import com.atlassian.bitbucket.idx.IndexingContext;
import com.atlassian.bitbucket.repository.Repository;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.Locale;

/**
 * {@link CommitIndexer} implementation that scans commit messages for JIRA keys and stores matches under the
 * "jira-key" property in the index.
 *
 * @since 4.0
 */
public class JiraKeyIndexer implements CommitIndexer {

    public static final String ID = "com.atlassian.bitbucket.JiraKeyIndexer";

    private static final Logger log = LoggerFactory.getLogger(JiraKeyIndexer.class);

    private final CommitIndex commitIndex;
    private final JiraKeyScanner scanner;

    public JiraKeyIndexer(CommitIndex commitIndex, JiraKeyScanner scanner) {
        this.commitIndex = commitIndex;
        this.scanner = scanner;
    }

    @Nonnull
    @Override
    public String getId() {
        return ID;
    }

    @Override
    public boolean isEnabledForRepository(@Nonnull Repository repository) {
        // always index JIRA keys. This ensures that when an application link to JIRA is created, all keys will already
        // be indexed. No surprises!
        return true;
    }

    @Override
    public void onAfterIndexing(@Nonnull IndexingContext context) {
        log.trace("Finished indexing with context: {}", context);
    }

    @Override
    public void onBeforeIndexing(@Nonnull IndexingContext context) {
        log.trace("Indexing with context: {}", context);
    }

    @Override
    public void onCommitAdded(@Nonnull Commit commit, @Nonnull IndexingContext ctx) {
        String message = commit.getMessage();
        if (message == null) {
            return;
        }

        Collection<String> keys = Lists.newArrayList(scanner.findAll(message));
        log.debug("Indexed {} (Matching JIRA keys: {})", commit.getId(), keys);

        for (String key : keys) {
            // Always uppercase for searching performance
            commitIndex.addProperty(commit.getId(), JiraConstants.IDX_PROP_ISSUE_KEYS, key.toUpperCase(Locale.US));
        }
    }

    @Override
    public void onCommitRemoved(@Nonnull Commit commit, @Nonnull IndexingContext ctx) {
        // no-op; the properties associated with the commit will be deleted automatically
        log.trace("Removing commit {}", commit.getId());
    }
}
