package com.intellij.openapi.diff.impl.external;

import com.intellij.openapi.diff.*;
import com.intellij.openapi.diff.impl.DiffPanelImpl;
import com.intellij.openapi.diff.impl.DiffUtil;
import com.intellij.openapi.diff.impl.FrameWrapper;
import com.intellij.openapi.ui.DialogBuilder;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.ex.MessagesEx;
import com.intellij.openapi.vfs.VirtualFile;

import javax.swing.*;
import java.awt.*;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;

// Author: dyoma

class FrameDiffTool implements DiffTool {
  public void show(DiffRequest request) {
    Collection hints = request.getHints();
    boolean shouldOpenDialog = shouldOpenDialog(hints);
    if (shouldOpenDialog) {
      DialogBuilder builder = new DialogBuilder(request.getProject());
      DiffPanelImpl diffPanel = createDiffPanelIfShouldShow(request, builder.getWindow());
      if (diffPanel == null) return;
      builder.setCenterPanel(diffPanel.getComponent());
      builder.addDisposable(diffPanel);
      builder.setPreferedFocusComponent(diffPanel.getPreferredFocusedComponent());
      builder.removeAllActions();
      builder.setTitle(request.getWindowTitle());
      builder.setDimensionServiceKey(request.getGroupKey());
      showDiffDialog(builder, hints);
    } else {
      FrameWrapper frameWrapper = new FrameWrapper(request.getGroupKey());
      DiffPanelImpl diffPanel = createDiffPanelIfShouldShow(request, frameWrapper.getFrame());
      if (diffPanel == null) return;
      frameWrapper.setTitle(request.getWindowTitle());
      DiffUtil.initDiffFrame(frameWrapper, diffPanel);
      frameWrapper.show();
    }
  }

  private DiffPanelImpl createDiffPanelIfShouldShow(DiffRequest request, Window window) {
    DiffPanelImpl diffPanel = (DiffPanelImpl)DiffManagerImpl.createDiffPanel(request, window);
    if (checkNoDifferenceAndNotify(diffPanel, request)) {
      diffPanel.dispose();
      diffPanel = null;
    }
    return diffPanel;
  }

  private void showDiffDialog(DialogBuilder builder, Collection hints) {
    builder.showModal(!hints.contains(DiffTool.HINT_SHOW_NOT_MODAL_DIALOG));
  }

  private boolean shouldOpenDialog(Collection hints) {
    if (hints.contains(DiffTool.HINT_SHOW_MODAL_DIALOG)) return true;
    if (hints.contains(DiffTool.HINT_SHOW_NOT_MODAL_DIALOG)) return true;
    if (hints.contains(DiffTool.HINT_SHOW_FRAME)) return false;
    return KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow() instanceof JDialog;
  }

  private boolean checkNoDifferenceAndNotify(DiffPanel diffPanel, DiffRequest data) {
    if (!diffPanel.hasDifferences()) {
      return !askForceOpenDiff(data);
    }
    return false;
  }

  private boolean askForceOpenDiff(DiffRequest data) {
    byte[] bytes1;
    byte[] bytes2;
    try {
      bytes1 = data.getContents()[0].getBytes();
      bytes2 = data.getContents()[1].getBytes();
    }
    catch (IOException e) {
      MessagesEx.error(data.getProject(), e.getMessage()).showNow();
      return false;
    }
    String message;
    if (Arrays.equals(bytes1, bytes2))
      message = DiffBundle.message("diff.contents.are.identical.message.text");
    else
      message = DiffBundle.message("diff.contents.have.differences.only.in.line.separators.message.text");
    Messages.showInfoMessage(data.getProject(), message, DiffBundle.message("no.differences.dialog.title"));
    return false;
    //return Messages.showDialog(data.getProject(), message + "\nShow diff anyway?", "No Differences", new String[]{"Yes", "No"}, 1,
    //                    Messages.getQuestionIcon()) == 0;
  }

  public boolean canShow(DiffRequest data) {
    DiffContent[] contents = data.getContents();
    if (contents.length != 2) return false;
    for (int i = 0; i < contents.length; i++) {
      DiffContent content = contents[i];
      if (content.isBinary()) return false;
      VirtualFile file = content.getFile();
      if (file != null && file.isDirectory()) return false;
    }
    return true;
  }
}

@@ -75,24 +75,80 @@
 api.diff.*;%0A
+import com.intellij.openapi.diff.impl.ComparisonPolicy;%0A
 import com.i
@@ -465,16 +465,59 @@
 ualFile;
+%0Aimport org.jetbrains.annotations.Nullable;
 %0A%0Aimport
@@ -1794,23 +1794,42 @@
 %0A  %7D%0A%0A  
-private
+@Nullable%0A  private static
  DiffPan
@@ -2049,16 +2049,24 @@
  request
+, window
 )) %7B%0A   
@@ -2156,16 +2156,23 @@
 private 
+static 
 void sho
@@ -2310,32 +2310,39 @@
 %0A  %7D%0A%0A  private 
+static 
 boolean shouldOp
@@ -2689,32 +2689,39 @@
 %0A  %7D%0A%0A  private 
+static 
 boolean checkNoD
@@ -2768,32 +2768,53 @@
 DiffRequest data
+, final Window window
 ) %7B%0A    if (!dif
@@ -2836,24 +2836,580 @@
 rences()) %7B%0A
+      DiffManagerImpl manager = (DiffManagerImpl) DiffManager.getInstance();%0A      if (!manager.getComparisonPolicy().equals(ComparisonPolicy.DEFAULT)) %7B%0A        ComparisonPolicy oldPolicy = manager.getComparisonPolicy();%0A        manager.setComparisonPolicy(ComparisonPolicy.DEFAULT);%0A        DiffPanel maybeDiffPanel = DiffManagerImpl.createDiffPanel(data, window);%0A        manager.setComparisonPolicy(oldPolicy);%0A%0A        boolean hasDiffs = maybeDiffPanel.hasDifferences();%0A        maybeDiffPanel.dispose();%0A%0A        if (hasDiffs) return false;%0A      %7D%0A%0A
       return
@@ -3473,16 +3473,23 @@
 private 
+static 
 boolean 
@@ -4531,53 +4531,8 @@
 or (
-int i = 0; i %3C contents.length; i++) %7B%0A      
 Diff
@@ -4547,17 +4547,17 @@
 content 
-=
+:
  content
@@ -4561,12 +4561,11 @@
 ents
-%5Bi%5D;
+) %7B
 %0A   

allow viewing diff if it has changes ignored by current comparison policy (IDEADEV-6689)