/*
 * Copyright 2003-2015 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 jetbrains.mps.ide.editorTabs.tabfactory.tabs.buttontabs;

import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.ActionPopupMenu;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CustomShortcutSet;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.KeyboardShortcut;
import com.intellij.openapi.actionSystem.ToggleAction;
import jetbrains.mps.ide.ModelReadAction;
import jetbrains.mps.ide.editorTabs.TabColorProvider;
import jetbrains.mps.ide.editorTabs.tabfactory.NodeChangeCallback;
import jetbrains.mps.ide.icons.IconManager;
import jetbrains.mps.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.openapi.model.SNodeReference;

import javax.swing.JComponent;
import javax.swing.JPopupMenu;
import javax.swing.KeyStroke;
import java.awt.Color;
import java.awt.Component;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

class SelectTabAction extends ToggleAction {
  private final Project myProject;
  private final ButtonEditorTab myTab;
  private final NodeChangeCallback myCallback;

  public SelectTabAction(@NotNull Project mpsProject, ButtonEditorTab tab, NodeChangeCallback callback) {
    super(tab.getDescriptor().getTitle(), "", tab.getDescriptor().getIcon());
    myProject = mpsProject;
    myTab = tab;
    myCallback = callback;
  }

  /*package*/ void registerShortcut(JComponent editor) {
    if (myTab.getDescriptor().getShortcutChar() != null) {
      KeyStroke keystroke = KeyStroke.getKeyStroke("alt shift " + myTab.getDescriptor().getShortcutChar());
      KeyboardShortcut shortcut = new KeyboardShortcut(keystroke, null);
      registerCustomShortcutSet(new CustomShortcutSet(shortcut), editor);
    }
  }

  @Override
  public boolean displayTextInToolbar() {
    return true;
  }

  @Override
  public boolean isSelected(AnActionEvent e) {
    return myTab.isSelected();
  }

  @Override
  public void setSelected(AnActionEvent e, boolean state) {
    myProject.getModelAccess().runReadAction(new Runnable() {
      @Override
      public void run() {
        List<SNodeReference> nodeRefs = myTab.getEditorNodes();
        ArrayList<SNode> nodes = new ArrayList<>();
        for (SNodeReference r : nodeRefs) {
          SNode n = r.resolve(myProject.getRepository());
          if (n != null) {
            nodes.add(n);
          }
        }
        if (nodes.size() == 1) {
          myCallback.changeNode(nodes.get(0).getReference());
          return;
        }

        Component component = myTab.getComponentForPopup();

        DefaultActionGroup group = getGotoGroup(nodes);
        ActionPopupMenu popup = ActionManager.getInstance().createActionPopupMenu(ActionPlaces.UNKNOWN, group);
        JPopupMenu popupMenu = popup.getComponent();
        popupMenu.show(component, 0, 0);

        TabColorProvider tabColorProvider = myTab.getColorProvider();
        if (tabColorProvider != null && popupMenu.getComponents().length == nodes.size()) {
          for (int i = 0; i < nodes.size(); i++) {
            SNode node = nodes.get(i);
            Component menuItem = popupMenu.getComponents()[i];
            Color color = tabColorProvider.getNodeColor(node);// WTF - TCP.getAspectColor takes SNodeReference, while TCP.getNodeColor - SNode
            if (color != null) {
              menuItem.setForeground(color);
            }
          }
        }
      }
    });
  }

  @NotNull
  private DefaultActionGroup getGotoGroup(List<SNode> nodes) {
    DefaultActionGroup result = new DefaultActionGroup();
    if (nodes.isEmpty()) {
      //this is normal since now we can't guarantee button deletion (e.g. remove reduction rule from mapping configuration when it's the last usage of a concept in generator)
      return result;
    }

    Set<SNode> added = new HashSet<>();
    for (final SNode node : nodes) {
      SNode root = node.getContainingRoot();
      if (added.contains(root)) {
        continue;
      }
      added.add(root);
      final NodeChangeRunnable delegate = new NodeChangeRunnable(node.getReference(), myCallback);
      result.add(new ModelReadAction(getActionName(node), "", IconManager.getIconFor(root), delegate));
    }
    return result;
  }

  private static String getActionName(SNode node) {
    String rootName = node.getContainingRoot().getPresentation();
    if (rootName != null) {
      return rootName.replaceAll("_", "__");
    }
    return "<no name>";
  }
}
