/*
 * Copyright (C) 2014 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.gct.testing;

import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Ordering;
import com.google.gct.testing.ui.AddCompareScreenshotPanel;
import com.google.gct.testing.ui.AddScreenshotListener;
import com.google.gct.testing.ui.WipePanel;
import com.google.gct.testing.ui.WipePanelCallback;
import com.intellij.execution.testframework.AbstractTestProxy;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.actionSystem.impl.ActionButton;
import com.intellij.openapi.actionSystem.impl.PresentationFactory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogBuilder;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.List;

public class ScreenshotComparisonDialog {

  private final Set<ScreenshotComparisonHeaderPanelListener> headerListeners = new HashSet<ScreenshotComparisonHeaderPanelListener>();

  private final Project myProject;
  private final AbstractTestProxy testTreeRoot;
  private final CloudTestConfigurationImpl configuration;
  private final ConfigurationInstance configurationInstance;
  @Nullable private final ConfigurationInstance anotherConfigurationInstance;
  private final List<TestName> allTests;
  private TestName currentTest;
  private final Map<String, ConfigurationResult> results;
  private int step = 1;
  private int maxStep = 1;
  private final List<ScreenshotComparisonPanel> screenshotPanels = new LinkedList<ScreenshotComparisonPanel>();
  private final Map<TestName, Integer> testToStep = new HashMap<TestName, Integer>();

  private JPanel myPanel;
  private JPanel myHeaderPanel;
  private JPanel myAllScreenshotsPanel;
  private JPanel myLeftHeaderPanel;
  private JPanel myRightHeaderPanel;
  private JPanel myScreenshotNamePanel;
  private JLabel myScreenshotNameLabel;
  private Window myWindow;
  private JComboBox myTestComboBox;
  private JLabel myStepLabel;
  private AddCompareScreenshotPanel addScreenshotPanel;
  private ActionButton myDecrementStepButton;
  private ActionButton myIncrementStepButton;
  private Function<ConfigurationResult,String> getName;


  public ScreenshotComparisonDialog(Project project,
                                    AbstractTestProxy testTreeRoot,
                                    CloudTestConfigurationImpl configuration,
                                    ConfigurationInstance configurationInstance,
                                    @Nullable ConfigurationInstance anotherConfigurationInstance,
                                    List<TestName> allTests,
                                    TestName currentTest,
                                    Map<String, ConfigurationResult> results) {
    myProject = project;
    this.testTreeRoot = testTreeRoot;
    this.configuration = configuration;
    this.configurationInstance = configurationInstance;
    this.anotherConfigurationInstance = anotherConfigurationInstance;
    this.allTests = allTests;
    this.currentTest = currentTest;
    this.results = results;
    for (TestName test : allTests) {
      testToStep.put(test, 1);
    }
  }

  public void showDialog() {
    DialogBuilder builder = new DialogBuilder(myProject);
    builder.setCenterPanel(myPanel);
    builder.setPreferredFocusComponent(myLeftHeaderPanel);
    builder.setTitle("Screenshot Viewer");
    builder.removeAllActions();

    populateHeaderPanel();

    createFirstScreenshotComparisonPanel(configurationInstance);

    addScreenshotPanel = new AddCompareScreenshotPanel();
    //addScreenshotPanel.setHeight(UIUtil.isUnderDarcula() ? 585 : 570);
    addScreenshotPanel.addListener(new AddScreenshotListener() {
      @Override
      public void addScreenshot() {
        addScreenshotComparisonPanel(screenshotPanels.get(screenshotPanels.size() - 1));
      }
    });

    myAllScreenshotsPanel.add(addScreenshotPanel.getPanel());

    myTestComboBox.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        TestName selectedTest = (TestName)myTestComboBox.getSelectedItem();
        if (!selectedTest.equals(currentTest)) {
          testToStep.put(currentTest, step);
          currentTest = selectedTest;
          step = testToStep.get(currentTest);
          notifyHeaderListenersAboutStep(false);
        }
        for (ScreenshotComparisonHeaderPanelListener headerListener : headerListeners) {
          headerListener.updateTest(selectedTest, true);
        }
        updateMaxStep();
      }
    });

    myTestComboBox.setRenderer(new DefaultListCellRenderer() {
      @Override
      public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
        JLabel label = (JLabel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        if (value instanceof TestName) {
          final TestName testName = (TestName)value;
          label.setText(testName.getDisplayName());
        }
        return label;
      }
    });

    myWindow = builder.getWindow();

    updateMaxStep();
    updateScreenshotName();
    builder.show();
  }

  public Window getWindow() {
    return myWindow;
  }

  private void createFirstScreenshotComparisonPanel(ConfigurationInstance configurationInstance) {
    ScreenshotComparisonPanel screenshotComparisonPanel =
      new ScreenshotComparisonPanel(this, null, testTreeRoot, configuration, configurationInstance,
                                    (TestName)myTestComboBox.getSelectedItem(), step, results);
    screenshotPanels.add(screenshotComparisonPanel);
    WipePanel wipePanel = screenshotComparisonPanel.getPanel();
    myAllScreenshotsPanel.add(wipePanel);
    wipePanel.instantReveal(new WipePanelCallback() {
      @Override
      public void panelRevealed() {
        fitWindow();
      }
    });
    headerListeners.add(screenshotComparisonPanel);
  }

  private void populateHeaderPanel() {
    //myLeftHeaderPanel.add(new JLabel("Test:"));
    myTestComboBox = new JComboBox();
    myTestComboBox.setModel(new DefaultComboBoxModel(new Vector(allTests)));
    myTestComboBox.setSelectedItem(currentTest);
    myLeftHeaderPanel.add(myTestComboBox);

    myScreenshotNameLabel = new JLabel("");
    myScreenshotNameLabel.setFont(myScreenshotNameLabel.getFont().deriveFont(Font.BOLD).deriveFont(18.0f));
    myScreenshotNamePanel.add(myScreenshotNameLabel);
    myScreenshotNamePanel.setBorder(new EmptyBorder(0, 15, 0, 0));

    AnAction decrementStepAction = new AnAction() {
      @Override
      public void actionPerformed(AnActionEvent e) {
        step--;
        // This is not expected to happen, but just in case.
        if (step < 1) {
          step = 1;
        }
        updateStepLabel();
        notifyHeaderListenersAboutStep(true);
      }
      @Override
      public void update(AnActionEvent event) {
        Presentation presentation = event.getPresentation();
        presentation.setIcon(AllIcons.Actions.Back);
      }

    };
    PresentationFactory presentationFactory = new PresentationFactory();
    myDecrementStepButton =
      new ActionButton(decrementStepAction, presentationFactory.getPresentation(decrementStepAction), "MyPlace", new Dimension(25, 25));
    myRightHeaderPanel.add(myDecrementStepButton);

    myStepLabel = new JLabel();
    myRightHeaderPanel.add(myStepLabel);

    AnAction incrementStepAction = new AnAction() {
      @Override
      public void actionPerformed(AnActionEvent e) {
        step++;
        // This is not expected to happen, but just in case.
        if (step > maxStep) {
          step = maxStep;
        }
        updateStepLabel();
        notifyHeaderListenersAboutStep(true);
      }
      @Override
      public void update(AnActionEvent event) {
        Presentation presentation = event.getPresentation();
        presentation.setIcon(AllIcons.Actions.Forward);
      }

    };
    myIncrementStepButton =
      new ActionButton(incrementStepAction, presentationFactory.getPresentation(incrementStepAction), "MyPlace", new Dimension(25, 25));

    myRightHeaderPanel.add(myIncrementStepButton);

    updateStepLabel();
  }

  private void notifyHeaderListenersAboutStep(boolean shouldUpdateImage) {
    updateScreenshotName();
    for (ScreenshotComparisonHeaderPanelListener headerListener : headerListeners) {
      headerListener.updateStep(step, shouldUpdateImage);
    }
  }

  private void updateScreenshotName() {
    myScreenshotNameLabel.setText("Screenshot name");
    for (ConfigurationResult result : results.values()) {
      String screenshotName = result.getScreenshotNameForTestAndStep(currentTest, step);
      if (!screenshotName.isEmpty()) {
        myScreenshotNameLabel.setText(screenshotName);
        break;
      }
    }
  }

  private void updateStepLabel() {
    myStepLabel.setText("Screenshot " + step + "/" + maxStep);

    myDecrementStepButton.setEnabled(step > 1);
    myIncrementStepButton.setEnabled(step < maxStep);
  }

  public void addScreenshotComparisonPanel(ScreenshotComparisonPanel createAfterPanel) {
    int index = 0;
    for (Component component : myAllScreenshotsPanel.getComponents()) {
      if (component == createAfterPanel.getPanel()) {
        ScreenshotComparisonPanel screenshotComparisonPanel =
          new ScreenshotComparisonPanel(this, createAfterPanel, testTreeRoot, configuration,
                                        createAfterPanel.computeSelectedConfigurationInstance(), (TestName)myTestComboBox.getSelectedItem(),
                                        step, results);
        screenshotPanels.add(index + 1, screenshotComparisonPanel);
        updateMaxStep();
        WipePanel newPanel = screenshotComparisonPanel.getPanel();
        myAllScreenshotsPanel.add(newPanel, index + 1);
        headerListeners.add(screenshotComparisonPanel);
        fitWindow();
        newPanel.reveal(null);
        return;
      }
      index++;
    }
    throw new IllegalArgumentException("Could not find panel to insert after: " + createAfterPanel);
  }

  public void fitWindow() {
    if (myWindow == null) {
      return;
    }
    myAllScreenshotsPanel.updateUI();
    myWindow.pack();
    int maxHeight = 0;
    for (ScreenshotComparisonPanel panel : screenshotPanels) {
      if (panel.getPanel().getHeight() > maxHeight) {
        maxHeight = panel.getPanel().getHeight();
      }
    }
    addScreenshotPanel.setHeight(maxHeight);
    myAllScreenshotsPanel.updateUI();
    myWindow.pack();
  }

  public void removeScreenshotComparisonPanel(final ScreenshotComparisonPanel removedPanel) {
    WipePanel panel = removedPanel.getPanel();
    panel.unReveal(new WipePanelCallback() {
      @Override
      public void panelHidden(WipePanel panel) {
        headerListeners.remove(removedPanel);
        screenshotPanels.remove(removedPanel);
        removedPanel.stopListeningToResults();

        myAllScreenshotsPanel.remove(panel);
        if (myAllScreenshotsPanel.getComponentCount() == 1) {
          myWindow.dispose();
        } else {
          updateMaxStep();
          fitWindow();
        }
      }
    });
  }

  void updateMaxStep() {
    maxStep = Ordering.natural().max(Iterables.transform(screenshotPanels, new Function<ScreenshotComparisonPanel, Integer>() {
      @Override
      public Integer apply(ScreenshotComparisonPanel panel) {
        return panel.getMaxStep();
      }
    }));
    int oldStep = step;
    step = Math.min(step, maxStep);
    // In case we got new screenshots.
    if (step == 0 && maxStep != 0) {
      step = 1;
    }
    updateStepLabel();
    if (step != oldStep) {
      notifyHeaderListenersAboutStep(true);
    }
  }
}
