/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * Licensed 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 com.intellij.codeInsight.template.impl;

import com.intellij.codeInsight.CodeInsightActionHandler;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.CodeInsightUtilBase;
import com.intellij.codeInsight.completion.PlainPrefixMatcher;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.lookup.*;
import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.codeInsight.template.CustomLiveTemplate;
import com.intellij.codeInsight.template.CustomLiveTemplateBase;
import com.intellij.codeInsight.template.CustomTemplateCallback;
import com.intellij.codeInsight.template.TemplateManager;
import com.intellij.diagnostic.AttachmentFactory;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;
import java.util.regex.Pattern;

public class ListTemplatesHandler implements CodeInsightActionHandler {

  private static final Logger LOG = Logger.getInstance(ListTemplatesHandler.class);

  @Override
  public void invoke(@NotNull final Project project, @NotNull final Editor editor, @NotNull PsiFile file) {
    if (!CodeInsightUtilBase.prepareEditorForWrite(editor)) return;
    if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)) {
      return;
    }
    EditorUtil.fillVirtualSpaceUntilCaret(editor);

    PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
    int offset = editor.getCaretModel().getOffset();
    List<TemplateImpl> applicableTemplates = TemplateManagerImpl.listApplicableTemplateWithInsertingDummyIdentifier(editor, file, false);

    Map<TemplateImpl, String> matchingTemplates = filterTemplatesByPrefix(applicableTemplates, editor, offset, false, true);
    MultiMap<String, CustomLiveTemplateLookupElement> customTemplatesLookupElements = getCustomTemplatesLookupItems(editor, file, offset);

    if (matchingTemplates.isEmpty()) {
      for (TemplateImpl template : applicableTemplates) {
        matchingTemplates.put(template, null);
      }
    }

    if (matchingTemplates.isEmpty() && customTemplatesLookupElements.isEmpty()) {
      HintManager.getInstance().showErrorHint(editor, CodeInsightBundle.message("templates.no.defined"));
      return;
    }

    showTemplatesLookup(project, editor, file, matchingTemplates, customTemplatesLookupElements);
  }

  public static Map<TemplateImpl, String> filterTemplatesByPrefix(@NotNull Collection<TemplateImpl> templates, @NotNull Editor editor,
                                                                  int offset, boolean fullMatch, boolean searchInDescription) {
    if (offset > editor.getDocument().getTextLength()) {
      LOG.error("Cannot filter templates, index out of bounds. Offset: " + offset,
                AttachmentFactory.createAttachment(editor.getDocument()));
    }
    CharSequence documentText = editor.getDocument().getCharsSequence().subSequence(0, offset);

    String prefixWithoutDots = computeDescriptionMatchingPrefix(editor.getDocument(), offset);
    Pattern prefixSearchPattern = Pattern.compile(".*\\b" + prefixWithoutDots + ".*");

    Map<TemplateImpl, String> matchingTemplates = new TreeMap<TemplateImpl, String>(TemplateListPanel.TEMPLATE_COMPARATOR);
    for (TemplateImpl template : templates) {
      String templateKey = template.getKey();
      if (fullMatch) {
        int startOffset = documentText.length() - templateKey.length();
        if (startOffset <= 0 || !Character.isJavaIdentifierPart(documentText.charAt(startOffset - 1))) {
          // after non-identifier
          if (StringUtil.endsWith(documentText, templateKey)) {
            matchingTemplates.put(template, templateKey);
          }
        }
      }
      else {
        for (int i = templateKey.length(); i > 0; i--) {
          String prefix = templateKey.substring(0, i);
          int startOffset = documentText.length() - i;
          if (startOffset > 0 && Character.isJavaIdentifierPart(documentText.charAt(startOffset - 1))) {
            // after java identifier
            continue;
          }
          if (StringUtil.endsWith(documentText, prefix)) {
            matchingTemplates.put(template, prefix);
            break;
          }
        }
      }

      if (searchInDescription) {
        String templateDescription = template.getDescription();
        if (!prefixWithoutDots.isEmpty() && templateDescription != null && prefixSearchPattern.matcher(templateDescription).matches()) {
          matchingTemplates.put(template, prefixWithoutDots);
        }
      }
    }

    return matchingTemplates;
  }

  private static void showTemplatesLookup(final Project project,
                                          final Editor editor,
                                          final PsiFile file,
                                          @NotNull Map<TemplateImpl, String> matchingTemplates,
                                          @NotNull MultiMap<String, CustomLiveTemplateLookupElement> customTemplatesLookupElements) {

    LookupImpl lookup = (LookupImpl)LookupManager.getInstance(project).createLookup(editor, LookupElement.EMPTY_ARRAY, "", new TemplatesArranger());
    for (Map.Entry<TemplateImpl, String> entry : matchingTemplates.entrySet()) {
      TemplateImpl template = entry.getKey();
      lookup.addItem(createTemplateElement(template), new PlainPrefixMatcher(StringUtil.notNullize(entry.getValue())));
    }

    for (Map.Entry<String, Collection<CustomLiveTemplateLookupElement>> entry : customTemplatesLookupElements.entrySet()) {
      for (CustomLiveTemplateLookupElement lookupElement : entry.getValue()) {
        lookup.addItem(lookupElement, new PlainPrefixMatcher(entry.getKey()));
      }
    }

    showLookup(lookup, file);
  }

  public static MultiMap<String, CustomLiveTemplateLookupElement> getCustomTemplatesLookupItems(@NotNull Editor editor,
                                                                                                @NotNull PsiFile file,
                                                                                                int offset) {
    final MultiMap<String, CustomLiveTemplateLookupElement> result = MultiMap.create();
    CustomTemplateCallback customTemplateCallback = new CustomTemplateCallback(editor, file);
    for (CustomLiveTemplate customLiveTemplate : TemplateManagerImpl.listApplicableCustomTemplates(editor, file, false)) {
      if (customLiveTemplate instanceof CustomLiveTemplateBase) {
        String customTemplatePrefix = ((CustomLiveTemplateBase)customLiveTemplate).computeTemplateKeyWithoutContextChecking(customTemplateCallback);
        if (customTemplatePrefix != null) {
          result.putValues(customTemplatePrefix, ((CustomLiveTemplateBase)customLiveTemplate).getLookupElements(file, editor, offset));
        }
      }
    }
    return result;
  }

  private static LiveTemplateLookupElement createTemplateElement(final TemplateImpl template) {
    return new LiveTemplateLookupElementImpl(template, false) {
      @Override
      public Set<String> getAllLookupStrings() {
        String description = template.getDescription();
        if (description == null) {
          return super.getAllLookupStrings();
        }
        return ContainerUtil.newHashSet(getLookupString(), description);
      }
    };
  }

  private static String computePrefix(TemplateImpl template, String argument) {
    String key = template.getKey();
    if (argument == null) {
      return key;
    }
    if (key.length() > 0 && Character.isJavaIdentifierPart(key.charAt(key.length() - 1))) {
      return key + ' ' + argument;
    }
    return key + argument;
  }

  public static void showTemplatesLookup(final Project project, final Editor editor, Map<TemplateImpl, String> template2Argument) {
    final LookupImpl lookup = (LookupImpl)LookupManager.getInstance(project).createLookup(editor, LookupElement.EMPTY_ARRAY, "",
                                                                                          new LookupArranger.DefaultArranger());
    for (TemplateImpl template : template2Argument.keySet()) {
      String prefix = computePrefix(template, template2Argument.get(template));
      lookup.addItem(createTemplateElement(template), new PlainPrefixMatcher(prefix));
    }

    showLookup(lookup, template2Argument);
  }

  private static void showLookup(LookupImpl lookup, @Nullable Map<TemplateImpl, String> template2Argument) {
    Editor editor = lookup.getEditor();
    Project project = editor.getProject();
    lookup.addLookupListener(new MyLookupAdapter(project, editor, template2Argument));
    lookup.refreshUi(false, true);
    lookup.showLookup();
  }

  private static void showLookup(LookupImpl lookup, @NotNull PsiFile file) {
    Editor editor = lookup.getEditor();
    Project project = editor.getProject();
    lookup.addLookupListener(new MyLookupAdapter(project, editor, file));
    lookup.refreshUi(false, true);
    lookup.showLookup();
  }

  @Override
  public boolean startInWriteAction() {
    return true;
  }

  private static String computeDescriptionMatchingPrefix(Document document, int offset) {
    CharSequence chars = document.getCharsSequence();
    int start = offset;
    while (true) {
      if (start == 0) break;
      char c = chars.charAt(start - 1);
      if (!(Character.isJavaIdentifierPart(c))) break;
      start--;
    }
    return chars.subSequence(start, offset).toString();
  }

  private static class MyLookupAdapter extends LookupAdapter {
    private final Project myProject;
    private final Editor myEditor;
    private final Map<TemplateImpl, String> myTemplate2Argument;
    private final PsiFile myFile;

    public MyLookupAdapter(Project project, Editor editor, @Nullable Map<TemplateImpl, String> template2Argument) {
      myProject = project;
      myEditor = editor;
      myTemplate2Argument = template2Argument;
      myFile = null;
    }

    public MyLookupAdapter(Project project, Editor editor, @Nullable PsiFile file) {
      myProject = project;
      myEditor = editor;
      myTemplate2Argument = null;
      myFile = file;
    }

    @Override
    public void itemSelected(final LookupEvent event) {
      FeatureUsageTracker.getInstance().triggerFeatureUsed("codeassists.liveTemplates");
      final LookupElement item = event.getItem();
      if (item instanceof LiveTemplateLookupElementImpl) {
        final TemplateImpl template = ((LiveTemplateLookupElementImpl)item).getTemplate();
        final String argument = myTemplate2Argument != null ? myTemplate2Argument.get(template) : null;
        new WriteCommandAction(myProject) {
          @Override
          protected void run(@NotNull Result result) throws Throwable {
            ((TemplateManagerImpl)TemplateManager.getInstance(myProject)).startTemplateWithPrefix(myEditor, template, null, argument);
          }
        }.execute();
      }
      else if (item instanceof CustomLiveTemplateLookupElement) {
        if (myFile != null) {
          new WriteCommandAction(myProject) {
            @Override
            protected void run(@NotNull Result result) throws Throwable {
              ((CustomLiveTemplateLookupElement)item).expandTemplate(myEditor, myFile);
            }
          }.execute();
        }
      }
    }
  }

  private static class TemplatesArranger extends LookupArranger {

    @Override
    public Pair<List<LookupElement>, Integer> arrangeItems(@NotNull Lookup lookup, boolean onExplicitAction) {
      LinkedHashSet<LookupElement> result = new LinkedHashSet<LookupElement>();
      List<LookupElement> items = getMatchingItems();
      for (LookupElement item : items) {
        if (item.getLookupString().startsWith(lookup.itemPattern(item))) {
          result.add(item);
        }
      }
      result.addAll(items);
      ArrayList<LookupElement> list = new ArrayList<LookupElement>(result);
      int selected = lookup.isSelectionTouched() ? list.indexOf(lookup.getCurrentItem()) : 0;
      return new Pair<List<LookupElement>, Integer>(list, selected >= 0 ? selected : 0);
    }

    @Override
    public LookupArranger createEmptyCopy() {
      return new TemplatesArranger();
    }
  }
}
