/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * 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.intellij.xdebugger.impl.evaluate.quick.common;

import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.concurrency.ResultConsumer;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.xdebugger.XDebuggerBundle;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.*;
import java.util.List;

/**
 * @author nik
 */
abstract class DebuggerTreeWithHistoryContainer<D> {
  private static final Logger LOG = Logger.getInstance(DebuggerTreeWithHistoryContainer.class);
  private static final int HISTORY_SIZE = 11;
  private final List<D> myHistory = new ArrayList<D>();
  private int myCurrentIndex = -1;
  protected final DebuggerTreeCreator<D> myTreeCreator;
  @NotNull protected final Project myProject;

  protected DebuggerTreeWithHistoryContainer(@NotNull D initialItem, @NotNull DebuggerTreeCreator<D> creator, @NotNull Project project) {
    myTreeCreator = creator;
    myProject = project;
    myHistory.add(initialItem);
  }

  protected JPanel createMainPanel(Tree tree) {
    JPanel mainPanel = new JPanel(new BorderLayout());
    mainPanel.add(ScrollPaneFactory.createScrollPane(tree), BorderLayout.CENTER);
    mainPanel.add(createToolbar(mainPanel, tree), BorderLayout.NORTH);
    return mainPanel;
  }

  private void updateTree() {
    D item = myHistory.get(myCurrentIndex);
    updateTree(item);
  }

  protected void updateTree(@NotNull D selectedItem) {
    updateContainer(myTreeCreator.createTree(selectedItem), myTreeCreator.getTitle(selectedItem));
  }

  protected abstract void updateContainer(Tree tree, String title);

  protected void addToHistory(final D item) {
    if (myCurrentIndex < HISTORY_SIZE) {
      if (myCurrentIndex != -1) {
        myCurrentIndex += 1;
      } else {
        myCurrentIndex = 1;
      }
      myHistory.add(myCurrentIndex, item);
    }
  }

  private JComponent createToolbar(JPanel parent, Tree tree) {
    DefaultActionGroup group = new DefaultActionGroup();
    group.add(new SetAsRootAction(tree));

    AnAction back = new GoBackwardAction();
    back.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.ALT_MASK)), parent);
    group.add(back);

    AnAction forward = new GoForwardAction();
    forward.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.ALT_MASK)), parent);
    group.add(forward);

    return ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true).getComponent();
  }

  private class GoForwardAction extends AnAction {
    public GoForwardAction() {
      super(CodeInsightBundle.message("quick.definition.forward"), null, AllIcons.Actions.Forward);
    }

    @Override
    public void actionPerformed(AnActionEvent e) {
      if (myHistory.size() > 1 && myCurrentIndex < myHistory.size() - 1){
        myCurrentIndex ++;
        updateTree();
      }
    }

    @Override
    public void update(AnActionEvent e) {
      e.getPresentation().setEnabled(myHistory.size() > 1 && myCurrentIndex < myHistory.size() - 1);
    }
  }

  private class GoBackwardAction extends AnAction {
    public GoBackwardAction() {
      super(CodeInsightBundle.message("quick.definition.back"), null, AllIcons.Actions.Back);
    }

    @Override
    public void actionPerformed(AnActionEvent e) {
      if (myHistory.size() > 1 && myCurrentIndex > 0) {
        myCurrentIndex--;
        updateTree();
      }
    }


    @Override
    public void update(AnActionEvent e) {
      e.getPresentation().setEnabled(myHistory.size() > 1 && myCurrentIndex > 0);
    }
  }

  private class SetAsRootAction extends AnAction {
    private Tree myTree;

    public SetAsRootAction(Tree tree) {
      super(XDebuggerBundle.message("xdebugger.popup.value.tree.set.root.action.tooltip"),
            XDebuggerBundle.message("xdebugger.popup.value.tree.set.root.action.tooltip"), AllIcons.Modules.UnmarkWebroot);
      myTree = tree;
    }

    @Override
    public void update(AnActionEvent e) {
      TreePath path = myTree.getSelectionPath();
      e.getPresentation().setEnabled(path != null && path.getPathCount() > 1);
    }

    @Override
    public void actionPerformed(AnActionEvent e) {
      TreePath path = myTree.getSelectionPath();
      if (path != null) {
        Object node = path.getLastPathComponent();
        myTreeCreator.createDescriptorByNode(node, new ResultConsumer<D>() {
          @Override
          public void onSuccess(final D value) {
            if (value != null) {
              ApplicationManager.getApplication().invokeLater(new Runnable() {
                @Override
                public void run() {
                  addToHistory(value);
                  updateTree(value);
                }
              });
            }
          }

          @Override
          public void onFailure(@NotNull Throwable t) {
            LOG.debug(t);
          }
        });
      }
    }
  }
}
