/*
 * Copyright 2000-2009 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.ui.content;

import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.*;
import com.intellij.ui.content.tabs.PinToolwindowTabAction;
import com.intellij.ui.content.tabs.TabbedContentAction;
import com.intellij.util.IJSwingUtilities;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.TabbedPaneUI;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;

/**
 * @author Eugene Belyaev
 * @author Anton Katilin
 * @author Vladimir Kondratyev
 */
public class TabbedPaneContentUI implements ContentUI, PropertyChangeListener {
  public static final String POPUP_PLACE = "TabbedPanePopup";

  private ContentManager myManager;
  private TabbedPaneWrapper myTabbedPaneWrapper;

  /**
   * Creates <code>TabbedPaneContentUI</code> with bottom tab placement.
   */
  public TabbedPaneContentUI() {
    this(JTabbedPane.BOTTOM);
  }

  /**
   * Creates <code>TabbedPaneContentUI</code> with cpecified tab placement.
   *
   * @param tabPlacement constant which defines where the tabs are located.
   *                     Acceptable values are <code>javax.swing.JTabbedPane#TOP</code>,
   *                     <code>javax.swing.JTabbedPane#LEFT</code>, <code>javax.swing.JTabbedPane#BOTTOM</code>
   *                     and <code>javax.swing.JTabbedPane#RIGHT</code>.
   */
  public TabbedPaneContentUI(int tabPlacement) {
    myTabbedPaneWrapper = new MyTabbedPaneWrapper(tabPlacement);
  }

  public JComponent getComponent() {
    return myTabbedPaneWrapper.getComponent();
  }

  public void setManager(@NotNull ContentManager manager) {
    if (myManager != null) {
      throw new IllegalStateException();
    }
    myManager = manager;
    myManager.addContentManagerListener(new MyContentManagerListener());
  }

  public void propertyChange(PropertyChangeEvent e) {
    if (Content.PROP_DISPLAY_NAME.equals(e.getPropertyName())) {
      Content content = (Content)e.getSource();
      int index = myTabbedPaneWrapper.indexOfComponent(content.getComponent());
      if (index != -1) {
        myTabbedPaneWrapper.setTitleAt(index, content.getTabName());
      }
    }
    else if (Content.PROP_DESCRIPTION.equals(e.getPropertyName())) {
      Content content = (Content)e.getSource();
      int index = myTabbedPaneWrapper.indexOfComponent(content.getComponent());
      if (index != -1) {
        myTabbedPaneWrapper.setToolTipTextAt(index, content.getDescription());
      }
    }
    else if (Content.PROP_COMPONENT.equals(e.getPropertyName())) {
      Content content = (Content)e.getSource();
      JComponent oldComponent = (JComponent)e.getOldValue();
      int index = myTabbedPaneWrapper.indexOfComponent(oldComponent);
      if (index != -1) {
        boolean hasFocus = IJSwingUtilities.hasFocus2(oldComponent);
        myTabbedPaneWrapper.setComponentAt(index, content.getComponent());
        if (hasFocus) {
          content.getComponent().requestDefaultFocus();
        }
      }
    }
    else if (Content.PROP_ICON.equals(e.getPropertyName())) {
      Content content = (Content)e.getSource();
      int index = myTabbedPaneWrapper.indexOfComponent(content.getComponent());
      if (index != -1) {
        myTabbedPaneWrapper.setIconAt(index, (Icon)e.getNewValue());
      }
    }
  }

  private Content getSelectedContent() {
    JComponent selectedComponent = myTabbedPaneWrapper.getSelectedComponent();
    return myManager.getContent(selectedComponent);
  }




  private class MyTabbedPaneWrapper extends TabbedPaneWrapper.AsJTabbedPane {
    public MyTabbedPaneWrapper(int tabPlacement) {
      super(tabPlacement);
    }

    protected TabbedPane createTabbedPane(int tabPlacement) {
      return new MyTabbedPane(tabPlacement);
    }

    protected TabbedPaneHolder createTabbedPaneHolder() {
      return new MyTabbedPaneHolder(this);
    }

    private class MyTabbedPane extends TabbedPaneImpl {
      public MyTabbedPane(int tabPlacement) {
        super(tabPlacement);
        addMouseListener(new MyPopupHandler());
        enableEvents(AWTEvent.MOUSE_EVENT_MASK);
      }

      private void closeTabAt(int x, int y) {
        TabbedPaneUI ui = getUI();
        int index = ui.tabForCoordinate(this, x, y);
        if (index < 0 || !myManager.canCloseContents()) {
          return;
        }
        final Content content = myManager.getContent(index);
        if (content != null && content.isCloseable()) {
          myManager.removeContent(content, true);
        }
      }

      /**
       * Hides selected menu.
       */
      private void hideMenu() {
        MenuSelectionManager menuSelectionManager = MenuSelectionManager.defaultManager();
        menuSelectionManager.clearSelectedPath();
      }

      protected void processMouseEvent(MouseEvent e) {
        if (e.isPopupTrigger()) { // Popup doesn't activate clicked tab.
          showPopup(e.getX(), e.getY());
          return;
        }

        if (!e.isShiftDown() && (MouseEvent.BUTTON1_MASK & e.getModifiers()) > 0) { // RightClick without Shift modifiers just select tab
          if (MouseEvent.MOUSE_RELEASED == e.getID()) {
            TabbedPaneUI ui = getUI();
            int index = ui.tabForCoordinate(this, e.getX(), e.getY());
            if (index != -1) {
              setSelectedIndex(index);
            }
            hideMenu();
          }
        }
        else if (e.isShiftDown() && (MouseEvent.BUTTON1_MASK & e.getModifiers()) > 0) { // Shift+LeftClick closes the tab
          if (MouseEvent.MOUSE_RELEASED == e.getID()) {
            closeTabAt(e.getX(), e.getY());
            hideMenu();
          }
        }
        else if ((MouseEvent.BUTTON2_MASK & e.getModifiers()) > 0) { // MouseWheelClick closes the tab
          if (MouseEvent.MOUSE_RELEASED == e.getID()) {
            closeTabAt(e.getX(), e.getY());
            hideMenu();
          }
        }
        else if ((MouseEvent.BUTTON3_MASK & e.getModifiers()) > 0 && SystemInfo.isWindows) { // Right mouse button doesn't activate tab
        }
        else {
          super.processMouseEvent(e);
        }
      }

      protected ChangeListener createChangeListener() {
        return new MyModelListener();
      }

      private class MyModelListener extends ModelListener {
        public void stateChanged(ChangeEvent e) {
          Content content = getSelectedContent();
          if (content != null) {
            myManager.setSelectedContent(content);
          }
          super.stateChanged(e);
        }
      }

      /**
       * @return content at the specified location.  <code>x</code> and <code>y</code> are in
       *         tabbed pane coordinate system. The method returns <code>null</code> if there is no contnt at the
       *         specified location.
       */
      private Content getContentAt(int x, int y) {
        TabbedPaneUI ui = getUI();
        int index = ui.tabForCoordinate(this, x, y);
        if (index < 0) {
          return null;
        }
        return myManager.getContent(index);
      }

      protected class MyPopupHandler extends PopupHandler {
        public void invokePopup(Component comp, int x, int y) {
          if (myManager.getContentCount() == 0) return;
          showPopup(x, y);
        }
      }

      /**
       * Shows showPopup menu at the specified location. The <code>x</code> and <code>y</code> coordinates
       * are in JTabbedPane coordinate system.
       */
      private void showPopup(int x, int y) {
        Content content = getContentAt(x, y);
        if (content == null) {
          return;
        }
        DefaultActionGroup group = new DefaultActionGroup();
        group.add(new TabbedContentAction.CloseAction(content));
        if (myTabbedPaneWrapper.getTabCount() > 1) {
          group.add(new TabbedContentAction.CloseAllAction(myManager));
          group.add(new TabbedContentAction.CloseAllButThisAction(content));
        }
        group.addSeparator();
        group.add(PinToolwindowTabAction.getPinAction());
        group.addSeparator();
        group.add(new TabbedContentAction.MyNextTabAction(myManager));
        group.add(new TabbedContentAction.MyPreviousTabAction(myManager));
        final List<AnAction> additionalActions = myManager.getAdditionalPopupActions(content);
        if (additionalActions != null) {
          group.addSeparator();
          for (AnAction anAction : additionalActions) {
            group.add(anAction);
          }
        }
        ActionPopupMenu menu = ActionManager.getInstance().createActionPopupMenu(POPUP_PLACE, group);
        menu.getComponent().show(myTabbedPaneWrapper.getComponent(), x, y);
      }
    }

    private class MyTabbedPaneHolder extends TabbedPaneHolder implements DataProvider {

      private MyTabbedPaneHolder(TabbedPaneWrapper wrapper) {
        super(wrapper);
      }

      public Object getData(String dataId) {
        if (PlatformDataKeys.CONTENT_MANAGER.is(dataId)) {
          return myManager;
        }
        if (PlatformDataKeys.NONEMPTY_CONTENT_MANAGER.is(dataId) && myManager.getContentCount() > 1) {
          return myManager;
        }
        return null;
      }
    }
  }

  private class MyContentManagerListener extends ContentManagerAdapter {
    public void contentAdded(ContentManagerEvent event) {
      Content content = event.getContent();
      myTabbedPaneWrapper.insertTab(content.getTabName(),
                                    content.getIcon(),
                                    content.getComponent(),
                                    content.getDescription(),
                                    event.getIndex());
      content.addPropertyChangeListener(TabbedPaneContentUI.this);
    }

    public void contentRemoved(ContentManagerEvent event) {
      event.getContent().removePropertyChangeListener(TabbedPaneContentUI.this);
      myTabbedPaneWrapper.removeTabAt(event.getIndex());
    }

    public void selectionChanged(ContentManagerEvent event) {
      int index = event.getIndex();
      if (index != -1) {
        myTabbedPaneWrapper.setSelectedIndex(index);
      }
    }
  }

  public boolean isSingleSelection() {
    return true;
  }

  public boolean isToSelectAddedContent() {
    return false;
  }

  public boolean canBeEmptySelection() {
    return false;
  }

  public void beforeDispose() {
  }

  public boolean canChangeSelectionTo(@NotNull Content content, boolean implicit) {
    return true;
  }

  @NotNull
  @Override
  public String getCloseActionName() {
    return UIBundle.message("tabbed.pane.close.tab.action.name");
  }

  @NotNull
  @Override
  public String getCloseAllButThisActionName() {
    return UIBundle.message("tabbed.pane.close.all.tabs.but.this.action.name");
  }

  @NotNull
  @Override
  public String getPreviousContentActionName() {
    return "Select Previous Tab";
  }

  @NotNull
  @Override
  public String getNextContentActionName() {
    return "Select Next Tab";
  }

  public void dispose() {
  }
}
