package org.asciidoc.intellij.actions.editorAction;

import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actionSystem.EditorTextInsertHandler;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.util.Producer;
import org.asciidoc.intellij.AsciiDocLanguage;
import org.asciidoc.intellij.actions.asciidoc.PasteImageAction;
import org.asciidoc.intellij.file.AsciiDocFileType;
import org.asciidoc.intellij.psi.AsciiDocUtil;
import org.jetbrains.annotations.NotNull;

import java.awt.datatransfer.Transferable;

/**
 * Paste an image from the clipboard when in editor.
 * Inspired by {@link com.intellij.codeInsight.editorActions.PasteHandler} and
 * https://plugins.jetbrains.com/plugin/8446-paste-images-into-markdown who showed me how to use this API.
 */
public class AsciiDocPasteImageHandler extends EditorActionHandler implements EditorTextInsertHandler {

  private final EditorActionHandler myOriginalHandler;

  public AsciiDocPasteImageHandler(EditorActionHandler originalAction) {
    myOriginalHandler = originalAction;
  }

  @Override
  public void doExecute(@NotNull final Editor editor, Caret caret, final DataContext dataContext) {
    assert caret == null : "Invocation of 'paste' operation for specific caret is not supported";
    execute(editor, dataContext, null);
  }

  @Override
  public void execute(Editor editor, DataContext dataContext, Producer<Transferable> producer) {
    if (editor instanceof EditorEx && editor.getProject() != null) {
      VirtualFile virtualFile = ((EditorEx) editor).getVirtualFile();
      if (virtualFile != null) {
        PsiFile file = PsiManager.getInstance(editor.getProject()).findFile(virtualFile);
        if (file != null) {
          PsiElement element = AsciiDocUtil.getStatementAtCaret(editor, file);
          // handle both language injection and start of empty file
          if ((element != null && AsciiDocLanguage.INSTANCE.equals(element.getLanguage())) ||
            AsciiDocFileType.INSTANCE.equals(virtualFile.getFileType())) {
            if (PasteImageAction.imageAvailable(producer)) {
              PasteImageAction action = new PasteImageAction();
              AnActionEvent event = createAnEvent(action, dataContext);
              action.actionPerformed(event);
              return;
            }
          }
        }
      }
    }

    if (myOriginalHandler != null) {
      if (myOriginalHandler instanceof EditorTextInsertHandler) {
        ((EditorTextInsertHandler) myOriginalHandler).execute(editor, dataContext, producer);
      } else {
        throw new IllegalStateException("original handler is not an instance of EditorTextInsertHandler, this is strange - please report: " + myOriginalHandler.getClass());
      }
    }
  }

  private AnActionEvent createAnEvent(AnAction action, @NotNull DataContext context) {
    Presentation presentation = action.getTemplatePresentation().clone();
    return new AnActionEvent(null, context, ActionPlaces.UNKNOWN, presentation, ActionManager.getInstance(), 0);
  }
}

@@ -1667,29 +1667,32 @@
 Override%0A  p
-ublic
+rotected
  void doExec
@@ -1873,17 +1873,25 @@
 d%22;%0A    
-e
+super.doE
 xecute(e
@@ -1888,32 +1888,39 @@
 oExecute(editor,
+ caret,
  dataContext, nu
@@ -1919,14 +1919,8 @@
 text
-, null
 );%0A 

call super method to preserve functionality of original handler (#584)