/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * 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.google.devrel.cluestick.studioclient;

import com.google.devrel.cluestick.searchservice.EventLog;

import com.appspot.cluestick_server.search.model.CodeResult;
import com.appspot.cluestick_server.search.model.Result;
import com.appspot.cluestick_server.search.model.ResultContext;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.EditorSettings;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.TextAnnotationGutterProvider;
import com.intellij.openapi.editor.colors.EditorFontType;
import com.intellij.openapi.editor.event.SelectionEvent;
import com.intellij.openapi.editor.event.SelectionListener;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.ex.EditorGutterComponentEx;
import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
import com.intellij.openapi.editor.markup.EffectType;
import com.intellij.openapi.editor.markup.HighlighterLayer;
import com.intellij.openapi.editor.markup.MarkupModel;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ui.UIUtil;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JComponent;
import javax.swing.JPanel;

/**
 * CodeBrowser implements Browser to show Cluestick search results containing code.
 */
class CodeBrowser extends JPanel implements Browser, Disposable {
  private static final Color HIGHLIGHT_BACKGROUND = UIUtil.getTreeUnfocusedSelectionBackground();
  private static final TextAttributes HIGHLIGHT_ATTRIBUTES =
      new TextAttributes(null, HIGHLIGHT_BACKGROUND, null, EffectType.SEARCH_MATCH, Font.BOLD);
  private static final Pattern WHITESPACE_PREFIX = Pattern.compile("^\\s*");

  private final EventLog eventLog;
  private final EditorEx editor;
  private final Document document;
  private final Project project;
  private final EditorHighlighterFactory highlighterFactory;
  private Result result;

  public CodeBrowser(@NotNull Project project, @NotNull EventLog eventLog) {
    super(new BorderLayout());
    this.project = project;
    this.eventLog = eventLog;

    highlighterFactory = EditorHighlighterFactory.getInstance();

    EditorFactory factory = EditorFactory.getInstance();
    document = factory.createDocument("");
    editor = (EditorEx) factory.createViewer(document, project);

    EditorSettings settings = editor.getSettings();
    settings.setLineNumbersShown(true);
    settings.setAnimatedScrolling(false);
    settings.setRefrainFromScrolling(true);

    EditorGutterComponentEx gutter = editor.getGutterComponentEx();
    gutter.setShowDefaultGutterPopup(false);
    gutter.revalidateMarkup();

    editor.getSelectionModel().addSelectionListener(new SelectionListener() {
      @Override
      public void selectionChanged(SelectionEvent e) {
        TextRange range = e.getNewRange();
        if (range.isEmpty()) {
          return;
        }
        // TODO(thorogood): event log constants
        CodeBrowser.this.eventLog.logEvent("select", getResultKey(), 0);
      }
    });

    // Add the component. Configure the preferred size to zero, as otherwise the Editor itself will
    // grow rather than fitting inside its scroll pane.
    JComponent component = editor.getComponent();
    component.setPreferredSize(new Dimension(0, 0));
    add(component, BorderLayout.CENTER);
  }

  @Override
  public void dispose() {
    EditorFactory factory = EditorFactory.getInstance();
    factory.releaseEditor(editor);
  }

  @Override
  public void showEmpty() {
    result = null;
    ApplicationManager.getApplication().runWriteAction(new Runnable() {
      @Override
      public void run() {
        document.setText("");
      }
    });
  }

  @Override
  public void showResult(Result result) {
    if (result == null || result.getCode() == null) {
      showEmpty();
      return;
    }
    this.result = result;

    CodeResult code = result.getCode();
    List<CharSequence> lines = new ArrayList<CharSequence>();
    int scrollTo = -1;

    List<Integer> highlightLines = new ArrayList<Integer>();
    List<ResultContext> allContext = code.getContext();
    if (allContext != null && !allContext.isEmpty()) {
      // If there's only a single result and it's at line one, it's likely the whole file.
      // Otherwise, the results contain snippets that can be displayed separately.
      boolean containsSnippets = !(allContext.size() == 1 && allContext.get(0).getStartAt() == 1);

      for (ResultContext context : allContext) {
        List<String> src = context.getSrc();
        if (src == null || src.isEmpty()) {
          continue;
        }

        src = formatCode(src);
        if (!containsSnippets) {
          if (scrollTo == -1 && !context.getResultsAt().isEmpty()) {
            scrollTo = context.getResultsAt().get(0);
          }
          for (int line : context.getResultsAt()) {
            highlightLines.add(line - 1);
          }
          lines.addAll(formatCode(src));
          continue;
        }

        // If this is a snippet, then annotate it as such.
        // TODO(thorogood): Different annotations if we ever show other languages (probably just
        // Python).
        StringBuilder dividerBuilder = new StringBuilder();
        int startAt = context.getStartAt();
        int endAt = startAt + src.size() - 1;
        if (endAt == startAt) {
          dividerBuilder.append("// Line ").append(startAt);
        } else {
          dividerBuilder.append(String.format("// Lines %d-%d", startAt, endAt));
          String resultsAt = StringUtil.join(context.getResultsAt(), ", ");
          if (!StringUtil.isEmpty(resultsAt)) {
            dividerBuilder.append(" (").append(resultsAt).append(')');
          }
        }
        lines.add(dividerBuilder);
        for (int line : context.getResultsAt()) {
          highlightLines.add(lines.size() + line - context.getStartAt());
        }
        lines.addAll(formatCode(src));
        lines.add("");
      }
    }

    if (scrollTo < 1) {
      scrollTo = 1;
    }
    // LogicalPosition is zero-indexed, but our code is one-indexed.
    LogicalPosition position = new LogicalPosition(scrollTo - 1, 0);
    setText(lines, position, highlightLines);

    String path = ResultUtils.getBaseName(code.getPath());
    editor.setHighlighter(highlighterFactory.createEditorHighlighter(project, path));
  }

  @Override
  public JPanel getPanel() {
    return this;
  }

  /**
   * @return The result key for the result currently being shown, if available.
   */
  @Nullable
  private String getResultKey() {
    if (result != null) {
      return result.getKey();
    }
    return null;
  }

  /**
   * Sets the text and cursor position in the current {@link EditorEx}.
   * @param lines The lines of code to render.
   * @param position The position to center on once lines are set.
   */
  private void setText(@NotNull List<? extends CharSequence> lines,
      @NotNull final LogicalPosition position,
      @NotNull final List<Integer> highlight) {
    final MarkupModel markup = editor.getMarkupModel();
    markup.removeAllHighlighters();

    final StringBuilder text = new StringBuilder();
    for (CharSequence line : lines) {
      text.append(line).append('\n');
    }
    ApplicationManager.getApplication().runWriteAction(new Runnable() {
      @Override
      public void run() {
        document.setText(text);
        editor.getCaretModel().moveToLogicalPosition(position);
        editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);

        int layer = HighlighterLayer.SELECTION - 1;
        for (int line : highlight) {
          markup.addLineHighlighter(line, layer, HIGHLIGHT_ATTRIBUTES);
        }

        editor.getGutterComponentEx().revalidateMarkup();
      }
    });
  }

  /**
   * Formats code for display. Currently just trims left whitespace.
   *
   * @param input Source code to format.
   * @return Formatted source code.
   */
  @NotNull
  public static List<String> formatCode(@NotNull List<String> input) {
    boolean knownPrefix = false;
    String prefix = "";

    for (String line : input) {
      Matcher m = WHITESPACE_PREFIX.matcher(line);
      if (!m.find()) {
        throw new IllegalStateException("empty regex should always match");
      }
      if (m.hitEnd()) {
        continue;  // blank line
      }
      String localPrefix = line.substring(0, m.end());
      if (!knownPrefix) {
        prefix = localPrefix;
        knownPrefix = true;
        continue;
      }

      // Find minimum common substring of prefix/localPrefix.
      int j = 0;
      int len = Math.min(prefix.length(), localPrefix.length());
      while (j < len && prefix.charAt(j) == localPrefix.charAt(j)) {
        ++j;
      }
      prefix = prefix.substring(0, j);
    }

    if (prefix.isEmpty()) {
      return input;
    }
    int plen = prefix.length();
    List<String> output = new ArrayList<String>(input.size());
    for (String src : input) {
      if (src.length() < plen) {
        output.add("");
      } else {
        output.add(src.substring(plen));
      }
    }
    return output;
  }
}
