package org.jetbrains.idea.maven.execution.cmd;

import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.completion.CompletionResultSet;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.codeInsight.lookup.TailTypeDecorator;
import com.intellij.util.TextFieldCompletionProvider;
import groovyjarjarcommonscli.Option;
import groovyjarjarcommonscli.Options;
import org.jetbrains.annotations.NotNull;

import java.util.Collection;

/**
 * @author Sergey Evdokimov
 */
public abstract class CommandLineCompletionProvider extends TextFieldCompletionProvider {

  private final Options myOptions;

  public CommandLineCompletionProvider(Options options) {
    super(true);

    myOptions = options;
  }

  @NotNull
  @Override
  protected String getPrefix(@NotNull String currentTextPrefix) {
    ParametersListLexer lexer = new ParametersListLexer(currentTextPrefix);
    while (lexer.nextToken()) {
      if (lexer.getTokenEnd() == currentTextPrefix.length()) {
        return lexer.getCurrentToken();
      }
    }

    return "";
  }

  protected LookupElement createLookupElement(@NotNull Option option, @NotNull String text) {
    LookupElementBuilder res = LookupElementBuilder.create(text);

    if (option.getDescription() != null) {
      return TailTypeDecorator.withTail(res.withTypeText(option.getDescription(), true), TailType.INSERT_SPACE);
    }

    return res;
  }

  protected abstract void addArgumentVariants(@NotNull CompletionResultSet result);

  @Override
  protected void addCompletionVariants(@NotNull String text, int offset, @NotNull String prefix, @NotNull CompletionResultSet result) {
    ParametersListLexer lexer = new ParametersListLexer(text);

    int argCount = 0;

    while (lexer.nextToken()) {
      if (offset < lexer.getTokenStart()) {
        break;
      }

      if (offset <= lexer.getTokenEnd()) {
        if (argCount == 0) {
          if (prefix.startsWith("--")) {
            for (Option option : (Collection<Option>)myOptions.getOptions()) {
              if (option.getLongOpt() != null) {
                result.addElement(createLookupElement(option, "--" + option.getLongOpt()));
              }
            }
          }
          else if (prefix.startsWith("-")) {
            for (Option option : (Collection<Option>)myOptions.getOptions()) {
              if (option.getOpt() != null) {
                result.addElement(createLookupElement(option, "-" + option.getOpt()));
              }
            }
          }
          else {
            addArgumentVariants(result);
          }
        }

        return;
      }

      if (argCount > 0) {
        argCount--;
      }
      else {
        String token = lexer.getCurrentToken();

        if (token.startsWith("-")) {
          Option option = myOptions.getOption(token);
          if (option != null) {
            int optionArgCount = option.getArgs();

            if (optionArgCount == Option.UNLIMITED_VALUES) {
              argCount = Integer.MAX_VALUE;
            }
            else if (optionArgCount != Option.UNINITIALIZED) {
              argCount = optionArgCount;
            }
          }
        }
      }
    }

    if (argCount > 0) {
      return;
    }

    addArgumentVariants(result);
  }

}
