package com.atlassian.stash.internal.web.soy.functions;

import com.atlassian.soy.renderer.JsExpression;
import com.atlassian.soy.renderer.SoyClientFunction;
import com.atlassian.soy.renderer.SoyServerFunction;
import com.atlassian.stash.internal.content.CommitMessage;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;

import java.util.List;
import java.util.Set;

public class ParseCommitMessageFunction implements SoyServerFunction<CommitMessage>, SoyClientFunction {

    private static final List<String> DELIMITERS = ImmutableList.of(
        "\n\n",
        "\n",
        ". "
    );

    @Override
    public String getName() {
        return "parseCommitMessage";
    }

    /**
     * Takes a string with the full commit message and parses it into separate subject and message components.
     *
     * This should be kept in sync with util/parse-commit-message.js
     */
    @Override
    public CommitMessage apply(Object... args) {
        validate(args);

        String message = (String) args[0];

        for (String delimiter : DELIMITERS) {
            int index = message.indexOf(delimiter);

            if (index != -1) {
                return new CommitMessage(
                    message.substring(0, index).replace('\n', ' ') + delimiter.trim(),
                    message.substring(index + delimiter.length())
                );
            }
        }

        return new CommitMessage(message, "");
    }

    @Override
    public Set<Integer> validArgSizes() {
        return ImmutableSet.of(1);
    }

    @Override
    public JsExpression generate(JsExpression... args) {
        return new JsExpression("require('bitbucket/internal/util/parse-commit-message').splitIntoSubjectAndBody(" + args[0].getText() + ")");
    }

    private static void validate(Object[] args) {
        SoyArgumentUtils.ensureArgumentTypeIsOneOf(args, 0, String.class);
    }
}
