/*
 * Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved.
 */

package com.intellij.coverage;

import com.intellij.application.options.colors.ColorAndFontOptions;
import com.intellij.application.options.colors.ColorAndFontPanelFactory;
import com.intellij.application.options.colors.NewColorAndFontPanel;
import com.intellij.application.options.colors.SimpleEditorPreview;
import com.intellij.codeInsight.hint.EditorFragmentComponent;
import com.intellij.codeInsight.hint.HintManagerImpl;
import com.intellij.coverage.actions.HideCoverageInfoAction;
import com.intellij.coverage.actions.ShowCoveringTestsAction;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.ex.EditorGutterComponentEx;
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.editor.markup.ActiveGutterRenderer;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.options.colors.pages.GeneralColorsPage;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.rt.coverage.data.LineCoverage;
import com.intellij.rt.coverage.data.LineData;
import com.intellij.ui.ColorUtil;
import com.intellij.ui.ColoredSideBorder;
import com.intellij.ui.HintHint;
import com.intellij.ui.LightweightHint;
import com.intellij.util.Function;
import com.intellij.util.ImageLoader;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.TreeMap;

/**
 * @author ven
 */
public class CoverageLineMarkerRenderer implements ActiveGutterRenderer {
  private static final int THICKNESS = 8;
  private final TextAttributesKey myKey;
  private final String myClassName;
  private final TreeMap<Integer, LineData> myLines;
  private final boolean myCoverageByTestApplicable;
  private final Function<Integer, Integer> myNewToOldConverter;
  private final Function<Integer, Integer> myOldToNewConverter;
  private final CoverageSuitesBundle myCoverageSuite;
  private final boolean mySubCoverageActive;

  protected CoverageLineMarkerRenderer(final TextAttributesKey textAttributesKey, @Nullable final String className, final TreeMap<Integer, LineData> lines,
                             final boolean coverageByTestApplicable,
                             final Function<Integer, Integer> newToOldConverter,
                             final Function<Integer, Integer> oldToNewConverter,
                             final CoverageSuitesBundle coverageSuite, boolean subCoverageActive) {
    myKey = textAttributesKey;
    myClassName = className;
    myLines = lines;
    myCoverageByTestApplicable = coverageByTestApplicable;
    myNewToOldConverter = newToOldConverter;
    myOldToNewConverter = oldToNewConverter;
    myCoverageSuite = coverageSuite;
    mySubCoverageActive = subCoverageActive;
  }

  public void paint(Editor editor, Graphics g, Rectangle r) {
    final TextAttributes color = editor.getColorsScheme().getAttributes(myKey);
    Color bgColor = color.getBackgroundColor();
    if (bgColor == null) {
      bgColor = color.getForegroundColor();
    }
    if (editor.getSettings().isLineNumbersShown() || ((EditorGutterComponentEx)editor.getGutter()).isAnnotationsShown()) {
      if (bgColor != null) {
        bgColor = ColorUtil.toAlpha(bgColor, 150);
      }
    }
    if (bgColor != null) {
      g.setColor(bgColor);
    }
    g.fillRect(0, r.y, THICKNESS, r.height);
    final LineData lineData = getLineData(editor.xyToLogicalPosition(new Point(0, r.y)).line);
    if (lineData != null && lineData.isCoveredByOneTest()) {
      g.drawImage( ImageLoader.loadFromResource("/gutter/unique.png"), 0, r.y, 8, 8, editor.getComponent());
    }
  }

  public static CoverageLineMarkerRenderer getRenderer(int lineNumber,
                                                       @Nullable final String className,
                                                       final TreeMap<Integer, LineData> lines,
                                                       final boolean coverageByTestApplicable,
                                                       @NotNull final CoverageSuitesBundle coverageSuite,
                                                       final Function<Integer, Integer> newToOldConverter,
                                                       final Function<Integer, Integer> oldToNewConverter, boolean subCoverageActive) {
    return new CoverageLineMarkerRenderer(getAttributesKey(lineNumber, lines), className, lines, coverageByTestApplicable, newToOldConverter,
                                          oldToNewConverter, coverageSuite, subCoverageActive);
  }

  public static TextAttributesKey getAttributesKey(final int lineNumber,
                                                   final TreeMap<Integer, LineData> lines) {

    return getAttributesKey(lines.get(lineNumber));
  }

  private static TextAttributesKey getAttributesKey(LineData lineData) {
    if (lineData != null) {
      switch (lineData.getStatus()) {
        case LineCoverage.FULL:
          return CodeInsightColors.LINE_FULL_COVERAGE;
        case LineCoverage.PARTIAL:
          return CodeInsightColors.LINE_PARTIAL_COVERAGE;
      }
    }

    return CodeInsightColors.LINE_NONE_COVERAGE;
  }

  public boolean canDoAction(final MouseEvent e) {
    return e.getX() < THICKNESS;
  }

  public void doAction(final Editor editor, final MouseEvent e) {
    e.consume();
    final JComponent comp = (JComponent)e.getComponent();
    final JRootPane rootPane = comp.getRootPane();
    final JLayeredPane layeredPane = rootPane.getLayeredPane();
    final Point point = SwingUtilities.convertPoint(comp, THICKNESS, e.getY(), layeredPane);
    showHint(editor, point, editor.xyToLogicalPosition(e.getPoint()).line);
  }

  private void showHint(final Editor editor, final Point point, final int lineNumber) {
    final JPanel panel = new JPanel(new BorderLayout());
    panel.add(createActionsToolbar(editor, lineNumber), BorderLayout.NORTH);

    final LineData lineData = getLineData(lineNumber);
    final EditorImpl uEditor;
    if (lineData != null && lineData.getStatus() != LineCoverage.NONE && !mySubCoverageActive) {
      final EditorFactory factory = EditorFactory.getInstance();
      final Document doc = factory.createDocument(getReport(editor, lineNumber));
      doc.setReadOnly(true);
      uEditor = (EditorImpl)factory.createEditor(doc, editor.getProject());
      panel.add(EditorFragmentComponent.createEditorFragmentComponent(uEditor, 0, doc.getLineCount(), false, false), BorderLayout.CENTER);
    } else {
      uEditor = null;
    }


    final LightweightHint hint = new LightweightHint(panel){
      @Override
      public void hide() {
        if (uEditor != null) EditorFactory.getInstance().releaseEditor(uEditor);
        super.hide();

      }
    };
    HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, point,
        HintManagerImpl.HIDE_BY_ANY_KEY | HintManagerImpl.HIDE_BY_TEXT_CHANGE | HintManagerImpl.HIDE_BY_OTHER_HINT | HintManagerImpl.HIDE_BY_SCROLLING, -1, false, new HintHint(editor, point));
  }

  private String getReport(final Editor editor, final int lineNumber) {
    final LineData lineData = getLineData(lineNumber);

    final Document document = editor.getDocument();
    final Project project = editor.getProject();
    assert project != null;

    final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document);
    assert psiFile != null;
    
    final int lineStartOffset = document.getLineStartOffset(lineNumber);
    final int lineEndOffset = document.getLineEndOffset(lineNumber);

    return myCoverageSuite.getCoverageEngine().generateBriefReport(editor, psiFile, lineNumber, lineStartOffset, lineEndOffset, lineData);
  }

  protected JComponent createActionsToolbar(final Editor editor, final int lineNumber) {

    final JComponent editorComponent = editor.getComponent();

    final DefaultActionGroup group = new DefaultActionGroup();
    final GotoPreviousCoveredLineAction prevAction = new GotoPreviousCoveredLineAction(editor, lineNumber);
    final GotoNextCoveredLineAction nextAction = new GotoNextCoveredLineAction(editor, lineNumber);

    group.add(prevAction);
    group.add(nextAction);

    prevAction.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.ALT_MASK|InputEvent.SHIFT_MASK)), editorComponent);
    nextAction.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.ALT_MASK|InputEvent.SHIFT_MASK)), editorComponent);

    final LineData lineData = getLineData(lineNumber);
    if (myCoverageByTestApplicable) {
      group.add(new ShowCoveringTestsAction(myClassName, lineData));
    }
    final AnAction byteCodeViewAction = ActionManager.getInstance().getAction("ByteCodeViewer");
    if (byteCodeViewAction != null) {
      group.add(byteCodeViewAction);
    }
    group.add(new EditCoverageColorsAction(editor, lineNumber));
    group.add(new HideCoverageInfoAction());

    final JComponent toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.FILEHISTORY_VIEW_TOOLBAR, group, true).getComponent();

    final Color background = ((EditorEx)editor).getBackgroundColor();
    final Color foreground = editor.getColorsScheme().getColor(EditorColors.CARET_COLOR);
    toolbar.setBackground(background);
    toolbar.setBorder(new ColoredSideBorder(foreground, foreground, lineData == null || lineData.getStatus() == LineCoverage.NONE || mySubCoverageActive ? foreground : null, foreground, 1));
    return toolbar;
  }

  public void moveToLine(final int lineNumber, final Editor editor) {
    final int firstOffset = editor.getDocument().getLineStartOffset(lineNumber);
    editor.getCaretModel().moveToOffset(firstOffset);
    editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);

    editor.getScrollingModel().runActionOnScrollingFinished(new Runnable() {
      public void run() {
        Point p = editor.visualPositionToXY(editor.offsetToVisualPosition(firstOffset));
        EditorGutterComponentEx editorComponent = (EditorGutterComponentEx)editor.getGutter();
        JLayeredPane layeredPane = editorComponent.getRootPane().getLayeredPane();
        p = SwingUtilities.convertPoint(editorComponent, THICKNESS, p.y, layeredPane);
        showHint(editor, p, lineNumber);
      }
    });
  }

  @Nullable
  public LineData getLineData(int lineNumber) {
    return myLines != null ? myLines.get(myNewToOldConverter != null ? myNewToOldConverter.fun(lineNumber).intValue() : lineNumber) : null;
  }

  public Color getErrorStripeColor(final Editor editor) {
    return editor.getColorsScheme().getAttributes(myKey).getErrorStripeColor();
  }

  private class GotoPreviousCoveredLineAction extends BaseGotoCoveredLineAction {

    public GotoPreviousCoveredLineAction(final Editor editor, final int lineNumber) {
      super(editor, lineNumber);
      copyFrom(ActionManager.getInstance().getAction(IdeActions.ACTION_PREVIOUS_OCCURENCE));
      getTemplatePresentation().setText("Previous Coverage Mark");
    }

    protected boolean hasNext(final int idx, final List<Integer> list) {
      return idx > 0;
    }

    protected int next(final int idx) {
      return idx - 1;
    }

    @Override
    public void update(AnActionEvent e) {
      super.update(e);
      final String nextChange = getNextChange();
      if (nextChange != null) {
        e.getPresentation().setText("Previous " + nextChange);
      }
    }
  }

  private class GotoNextCoveredLineAction extends BaseGotoCoveredLineAction {

    public GotoNextCoveredLineAction(final Editor editor, final int lineNumber) {
      super(editor, lineNumber);
      copyFrom(ActionManager.getInstance().getAction(IdeActions.ACTION_NEXT_OCCURENCE));
      getTemplatePresentation().setText("Next Coverage Mark");
    }

    protected boolean hasNext(final int idx, final List<Integer> list) {
      return idx < list.size() - 1;
    }

    protected int next(final int idx) {
      return idx + 1;
    }

    @Override
    public void update(AnActionEvent e) {
      super.update(e);
      final String nextChange = getNextChange();
      if (nextChange != null) {
        e.getPresentation().setText("Next " + nextChange);
      }
    }
  }

  private abstract class BaseGotoCoveredLineAction extends AnAction {
    private final Editor myEditor;
    private final int myLineNumber;

    public BaseGotoCoveredLineAction(final Editor editor, final int lineNumber) {
      myEditor = editor;
      myLineNumber = lineNumber;
    }

    public void actionPerformed(final AnActionEvent e) {
      final Integer lineNumber = getLineEntry();
      if (lineNumber != null) {
        moveToLine(lineNumber.intValue(), myEditor);
      }
    }

    protected abstract boolean hasNext(int idx, List<Integer> list);
    protected abstract int next(int idx);

    @Nullable
    private Integer getLineEntry() {
      final ArrayList<Integer> list = new ArrayList<Integer>(myLines.keySet());
      Collections.sort(list);
      final LineData data = getLineData(myLineNumber);
      final int currentStatus = data != null ? data.getStatus() : LineCoverage.NONE;
      int idx = list.indexOf(myNewToOldConverter != null ? myNewToOldConverter.fun(myLineNumber).intValue() : myLineNumber);
      while (hasNext(idx, list)) {
        final int index = next(idx);
        final LineData lineData = myLines.get(list.get(index));
        idx = index;
        if (lineData != null && lineData.getStatus() != currentStatus) {
          final Integer line = list.get(idx);
          if (myOldToNewConverter != null) {
            final int newLine = myOldToNewConverter.fun(line).intValue();
            if (newLine != 0) return newLine;
          } else {
            return line;
          }
        }
      }
      return null;
    }

    @Nullable
    protected String getNextChange() {
      Integer entry = getLineEntry();
      if (entry != null) {
        final LineData lineData = getLineData(entry);
        if (lineData != null) {
          switch (lineData.getStatus()) {
            case LineCoverage.NONE: 
              return "Uncovered";
            case LineCoverage.PARTIAL:
              return "Partial Covered";
            case LineCoverage.FULL:
              return "Fully Covered";
          }
        }
      }
      return null;
    }

    @Override
    public void update(final AnActionEvent e) {
      e.getPresentation().setEnabled(getLineEntry() != null);
    }
  }

  private class EditCoverageColorsAction extends AnAction {
    private final Editor myEditor;
    private final int myLineNumber;

    private EditCoverageColorsAction(Editor editor, int lineNumber) {
      super("Edit coverage colors", "Edit coverage colors", AllIcons.General.EditColors);
      myEditor = editor;
      myLineNumber = lineNumber;
    }

    @Override
    public void update(AnActionEvent e) {
      e.getPresentation().setVisible(getLineData(myLineNumber) != null);
    }

    @Override
    public void actionPerformed(AnActionEvent e) {
      final ColorAndFontOptions colorAndFontOptions = new ColorAndFontOptions(){
        @Override
        protected List<ColorAndFontPanelFactory> createPanelFactories() {
          final GeneralColorsPage colorsPage = new GeneralColorsPage();
          final ColorAndFontPanelFactory panelFactory = new ColorAndFontPanelFactory() {
            @NotNull
            @Override
            public NewColorAndFontPanel createPanel(@NotNull ColorAndFontOptions options) {
              final SimpleEditorPreview preview = new SimpleEditorPreview(options, colorsPage);
              return NewColorAndFontPanel.create(preview, colorsPage.getDisplayName(), options, null, colorsPage);
            }

            @NotNull
            @Override
            public String getPanelDisplayName() {
              return "Editor | " + getDisplayName() + " | " + colorsPage.getDisplayName();
            }
          };
          return Collections.singletonList(panelFactory);
        }
      };
      final Configurable[] configurables = colorAndFontOptions.buildConfigurables();
      try {
        final SearchableConfigurable general = colorAndFontOptions.findSubConfigurable(GeneralColorsPage.class);
        if (general != null) {
          final LineData lineData = getLineData(myLineNumber);
          ShowSettingsUtil.getInstance().editConfigurable(myEditor.getProject(), general,
                                                          general.enableSearch(getAttributesKey(lineData).getExternalName()));
        }
      }
      finally {
        for (Configurable configurable : configurables) {
          configurable.disposeUIResources();
        }
        colorAndFontOptions.disposeUIResources();
      }
    }
  }
}
