/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.ignite.ci.tcbot.visa;

import com.google.common.base.Strings;
import java.util.Collection;
import java.util.Objects;
import javax.inject.Inject;
import javax.ws.rs.QueryParam;
import org.apache.ignite.ci.di.cache.GuavaCached;
import org.apache.ignite.ci.github.PullRequest;
import org.apache.ignite.ci.github.ignited.IGitHubConnIgnitedProvider;
import org.apache.ignite.ci.github.pure.IGitHubConnection;
import org.apache.ignite.ci.jira.ignited.IJiraIgnitedProvider;
import org.apache.ignite.ci.jira.ignited.TicketCompacted;
import org.apache.ignite.ci.jira.pure.Ticket;
import org.apache.ignite.ci.tcbot.conf.IGitHubConfig;
import org.apache.ignite.ci.tcbot.conf.IJiraServerConfig;
import org.apache.ignite.ci.tcbot.conf.ITcBotConfig;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 *
 */
public class BranchTicketMatcher {
    /** Config. */
    @Inject private ITcBotConfig cfg;

    /** GitHub connection ignited provider. */
    @Inject private IGitHubConnIgnitedProvider gitHubProvider;

    /** JIRA provider */
    @Inject private IJiraIgnitedProvider jiraIgnProv;

    @Nullable public String resolveTcBranchForPrLess(Ticket ticket,
        IJiraServerConfig jiraCfg,
        IGitHubConfig gitHubCfg) {
        String branchNumPrefix = jiraCfg.branchNumPrefix();

        if (Strings.isNullOrEmpty(branchNumPrefix)) {
            //an easy way, no special branch and ticket mappings specified, use project code.
            int ticketId = ticket.keyWithoutProject(jiraCfg.projectCodeForVisa());

            return gitHubCfg.gitBranchPrefix() + ticketId;
        }

        String branchJiraIdentification = findFixPrefixedNoInValues(branchNumPrefix,
            ticket.key,
            ticket.fields.summary,
            ticket.fields.customfield_11050);

        return convertJiraToGit(branchJiraIdentification, branchNumPrefix, gitHubCfg);

    }

    /**
     * Converts JIRA notation branch name to actual git branch name. Usually it is just lower-casing, but any mapping
     * may be configured.
     *
     * @param branchJiraIdentification Branch jira identification.
     * @param branchNumPrefix Branch number prefix.
     * @param gitHubCfg GH connection config.
     */
    private String convertJiraToGit(String branchJiraIdentification,
        String branchNumPrefix,
        IGitHubConfig gitHubCfg) {
        if (Strings.isNullOrEmpty(branchJiraIdentification))
            return null;

        return gitHubCfg.gitBranchPrefix() + branchJiraIdentification.substring(branchNumPrefix.length());
    }

    /**
     * @param tickets Tickets.
     * @param pr Pr.
     * @param jiraCfg Jira config.
     */
    @Nullable public String resolveTicketIdForPrBasedContrib(Collection<Ticket> tickets, PullRequest pr,
        IJiraServerConfig jiraCfg) {
        String branchNumPrefix = jiraCfg.branchNumPrefix();

        if (Strings.isNullOrEmpty(branchNumPrefix)) {
            //an easy way, no special branch and ticket mappings specified, use project code.
            String jiraPrefix = jiraCfg.projectCodeForVisa() + TicketCompacted.PROJECT_DELIM;

            return findFixPrefixedNumber(pr.getTitle(), jiraPrefix);
        }

        String prTitle = pr.getTitle();

        String branchNum = findFixPrefixedNumber(prTitle, branchNumPrefix);

        if (branchNum == null) // PR does not mention
            return null;

        return findTicketMentions(tickets, branchNum);
    }

    /**
     * @param srvCode Server code.
     * @param branchNum Branch number to be checked.
     */
    @SuppressWarnings("WeakerAccess")
    @GuavaCached(maximumSize = 3000, expireAfterWriteSecs = 60, cacheNullRval = true)
    protected String findTicketMentions(String srvCode, @Nullable String branchNum) {
        return findTicketMentions(jiraIgnProv.server(srvCode).getTickets(), branchNum);
    }

    /**
     * @param tickets Tickets.
     * @param branchNum Branch number to be checked.
     */
    @Nullable private String findTicketMentions(Collection<Ticket> tickets, @Nullable String branchNum) {
        if (Strings.isNullOrEmpty(branchNum))
            return null;

        return tickets.stream()
            .map(t -> t.key)
            .filter(k -> Objects.equals(k, branchNum))
            .findFirst()
            .orElseGet(() -> findTicketMentionsInSupplementaryFields(tickets, branchNum));
    }

    /**
     * @param tickets Tickets.
     * @param branchNum Branch number to be checked.
     */
    @Nullable private String findTicketMentionsInSupplementaryFields(Collection<Ticket> tickets, String branchNum) {
        if (Strings.isNullOrEmpty(branchNum))
            return null;

        return tickets.stream()
            .filter(t -> mentionsBranch(branchNum, t))
            .findFirst()
            .map(t -> t.key)
            .orElse(null);
    }

    /**
     * @param branchName Full branch name in jira.
     * @param ticket Ticket.
     */
    private boolean mentionsBranch(String branchName, Ticket ticket) {
        String summary = ticket.fields.summary;
        if (summary != null && summary.contains(branchName))
            return true;

        String val = ticket.fields.customfield_11050;
        if (val != null && val.contains(branchName))
            return true;

        return false;
    }

    @Nullable private String findFixPrefixedNoInValues(@NotNull String prefix, String... values) {
        for (String value : values) {
            String fixPrefixedNum = findFixPrefixedNumber(value, prefix);

            if (fixPrefixedNum != null)
                return fixPrefixedNum;
        }
        return null;
    }

    /**
     * @param val Pull Request/Ticket title prefix or other text to find constant-prefix text.
     * @param prefix Ticket prefix.
     * @return Branch number or null.
     */
    @Nullable private String findFixPrefixedNumber(@Nullable String val, @NotNull String prefix) {
        if (Strings.isNullOrEmpty(val))
            return null;

        int idxOfBranchNum = val.toUpperCase().indexOf(prefix.toUpperCase());

        if (idxOfBranchNum < 0)
            return null;

        int beginIdx = prefix.length() + idxOfBranchNum;
        int endIdx = beginIdx;

        while (endIdx < val.length() && Character.isDigit(val.charAt(endIdx)))
            endIdx++;

        if (endIdx == beginIdx)
            return null;

        return prefix + val.substring(beginIdx, endIdx);
    }

    /**
     *
     */
    public static class TicketNotFoundException extends Exception {
        TicketNotFoundException(String msg) {
            super(msg);
        }

        TicketNotFoundException(String msg, Exception e) {
            super(msg, e);
        }
    }

    public String resolveTicketFromBranch(String srvCode, String ticketFullName,
        String branchForTc) throws TicketNotFoundException {
        if (!Strings.isNullOrEmpty(ticketFullName))
            return ticketFullName; //old code probably not needed now; ticketFullName = ticketFullName.toUpperCase().startsWith(prefix) ? ticketFullName : prefix + ticketFullName;

        IJiraServerConfig jiraCfg = cfg.getJiraConfig(srvCode);
        IGitHubConfig gitCfg = cfg.getGitConfig(srvCode);

        PullRequest pr; // filled only when special PR found

        String ticketPrefix;
        try {
            String branchNumPrefix = jiraCfg.branchNumPrefix();

            ticketPrefix = Strings.isNullOrEmpty(branchNumPrefix)
                ? jiraCfg.projectCodeForVisa() + TicketCompacted.PROJECT_DELIM
                : branchNumPrefix;

            String prLessTicket = prLessTicket(branchForTc, ticketPrefix, gitCfg);
            if (!Strings.isNullOrEmpty(prLessTicket)) {
                if (Strings.isNullOrEmpty(branchNumPrefix)) {
                    //Default, simple case

                    return prLessTicket; //find out PRless ticket,
                }
                else {
                    // PR less ticket only mentioned in real ticket
                    String ticket = findTicketMentions(srvCode, prLessTicket);

                    if (!Strings.isNullOrEmpty(ticket))
                        return ticket; // found real JIRA ticket for comment
                }
            }

            pr = findPrForBranch(srvCode, branchForTc);
            if (pr != null) {
                String jiraPrefixInPr = findFixPrefixedNumber(pr.getTitle(), ticketPrefix);

                String ticketFromPr;
                if (Strings.isNullOrEmpty(branchNumPrefix)) {
                    //Default, simple case, branch name matching gives us a ticket
                    ticketFromPr = jiraPrefixInPr;
                }
                else {
                    ticketFromPr = Strings.isNullOrEmpty(jiraPrefixInPr)
                        ? null
                        : findTicketMentions(srvCode, jiraPrefixInPr);
                }

                if (!Strings.isNullOrEmpty(ticketFromPr))
                    return ticketFromPr; // found real JIRA ticket for comment
            }
        }
        catch (Exception e) {
            throw new TicketNotFoundException("Exception happened when server tried to get ticket ID from Pull Request - " + e.getMessage(), e);
        }

        throw new TicketNotFoundException("JIRA ticket can't be found - " +
            "PR title \"" + (pr == null ? "" : pr.getTitle()) + "\" should starts with \"" + ticketPrefix + "NNNNN\"." +
            " Please, rename PR according to the" +
            " <a href='https://cwiki.apache.org/confluence/display/IGNITE/How+to+Contribute" +
            "#HowtoContribute-1.CreateGitHubpull-request'>contributing guide</a>" +
            " or use branch name according ticket name.");
    }

    @Nullable private PullRequest findPrForBranch(
        @Nullable @QueryParam("serverId") String srvId,
        @Nullable @QueryParam("branchName") String branchForTc) {
        Integer prId = IGitHubConnection.convertBranchToPrId(branchForTc);

        if (prId == null)
            return null;

        return gitHubProvider.server(srvId).getPullRequest(prId);
    }

    /**
     * @param branchForTc Branch for tc.
     * @param ticketPrefix JIRA Ticket prefix.
     * @param gitHubIgn GitHub connection ign.
     */
    @Nullable private static String prLessTicket(String branchForTc,
        String ticketPrefix,
        IGitHubConfig gitHubIgn) {
        String branchPrefix = gitHubIgn.gitBranchPrefix();

        if (!branchForTc.startsWith(branchPrefix))
            return null;

        try {
            int ticketNum = Integer.parseInt(branchForTc.substring(branchPrefix.length()));

            return ticketPrefix + ticketNum;
        }
        catch (NumberFormatException ignored) {
        }

        return null;
    }
}
