/*
 * Licensed Materials - Property of Rogue Wave Software, Inc. 
 * © Copyright Rogue Wave Software, Inc. 2014, 2015 
 * © Copyright IBM Corp. 2009, 2014
 * © Copyright ILOG 1996, 2009
 * All Rights Reserved.
 *
 * Note to U.S. Government Users Restricted Rights:
 * The Software and Documentation were developed at private expense and
 * are "Commercial Items" as that term is defined at 48 CFR 2.101,
 * consisting of "Commercial Computer Software" and
 * "Commercial Computer Software Documentation", as such terms are
 * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4,
 * as applicable.
 */
package utils.sdm;

import ilog.views.IlvApplyObject;
import ilog.views.IlvGraphic;
import ilog.views.io.IlvInputStream;
import ilog.views.io.IlvPersistentObject;
import ilog.views.io.IlvReadFileException;
import ilog.views.maps.IlvMapUtil;
import ilog.views.maps.symbology.swing.IlvAbstractGroupTreeViewActions;
import ilog.views.maps.symbology.swing.IlvSymbologyTreeView;
import ilog.views.maps.symbology.swing.IlvSymbologyTreeViewActions;
import ilog.views.maps.symbology.swing.IlvTablePersistentContext;
import ilog.views.sdm.IlvSDMModel;
import ilog.views.util.swing.IlvSwingUtil;

import java.awt.Container;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Hashtable;

import javax.swing.JComboBox;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;

/**
 * Class that combines actions from more than one single <code>IlvSymbologyTreeViewActions</code>
 * This class relies on the fact that each symbol tag (as per {@link IlvSDMModel#getTag(Object)}) is assoiated to only a single actions class.
 */
public class CombinedTreeViewActions extends IlvAbstractGroupTreeViewActions {
  // association between symbol tags and actions instance.
  final private Hashtable<String, IlvSymbologyTreeViewActions> association = new Hashtable<String, IlvSymbologyTreeViewActions>();
  // table of actions instance.
  final private IlvSymbologyTreeViewActions[] actionTable;
  // should this class show a popup menu to select the type of symbol ?
  static boolean usePopup=true;
  // popup penu created.
  private JPopupMenu pm;
  //JV-6361
  /**
   * Class used to store and retrieve the persistent context of each action.
   * For compatibility reason (to load files created before 8.7). 
   * @deprecated Since JViews 8.8, this is replaced by <code>IlvTablePersistentContext</code>
   */
  static public class TableContext extends IlvTablePersistentContext {
      /**
       * Creates a new <code>TableContext</code>.
       * @param stream input stream
       * @throws IlvReadFileException
       */
    public TableContext(IlvInputStream stream) throws IlvReadFileException {
        super(stream);
    }
  }
  /**
   * Creates a new <code>CombinedTreeViewActions</code>.
   * @param actionTable table of the actions that the user can choose from.
   */
  public CombinedTreeViewActions(IlvSymbologyTreeViewActions[] actionTable) {
    this.actionTable = actionTable;
  }

  /** {@inheritDoc}*/
  public void actOnSymbologyChanged() {
    // not implemented
  }
  /** {@inheritDoc}*/
  public void createSymbol(final IlvSDMModel model, final Object group, final IlvApplyObject applier) {
    if (usePopup) {
      if (pm == null) {
        pm = new JPopupMenu();
        for (int i = 0; i < actionTable.length; i++) {
          final IlvSymbologyTreeViewActions action = actionTable[i];
          JMenuItem b = new JMenuItem(actionTable[i].toString());
          b.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
              IlvApplyObject applier2 = new IlvApplyObject() {
                public void apply(IlvGraphic obj, Object node) {
                  applier.apply(obj, node);
                  setNodeAction(model.getTag(node), action);
                }
              };
              action.createSymbol(model, group, applier2);
            }
          });
          pm.add(b);
        }
      }
      Point p = getView().getMousePosition(true);
      if (p == null) {
        Container tl=getView().getTopLevelAncestor();
        p = tl.getMousePosition(true);
        if(p==null){
          pm.show(getView(), 0,0);
        } else {
          p=IlvSwingUtil.convertPoint(tl, p, getView());
          pm.show(getView(), p.x, p.y);
        }
      } else {
        pm.show(getView(), p.x, p.y);
      }
    } else {
      JComboBox combo = new JComboBox(actionTable);
      int ans = JOptionPane.showConfirmDialog(getView(), combo, IlvMapUtil.getString(CombinedTreeViewActions.class,
          "CombinedTreeViewActions.choseSymbolType"), //$NON-NLS-1$
          JOptionPane.OK_CANCEL_OPTION);
      if (ans == JOptionPane.OK_OPTION) {
        final IlvSymbologyTreeViewActions action = actionTable[combo.getSelectedIndex()];
        IlvApplyObject applier2 = new IlvApplyObject() {
          public void apply(IlvGraphic obj, Object node) {
            applier.apply(obj, node);
            setNodeAction(model.getTag(node), action);
          }
        };
        action.createSymbol(model, group, applier2);
      }
    }
  }

  /** {@inheritDoc}*/
  public Object dropSymbolAt(IlvSDMModel model, Object data, Double lonRad, Double latRad) {
    for (int i = 0; i < actionTable.length; i++) {
      Object node = actionTable[i].dropSymbolAt(model, data, lonRad, latRad);
      if (node != null) {
        setNodeAction(model.getTag(node), actionTable[i]);
        return node;
      }
    }
    return null;
  }

  /** {@inheritDoc}*/
  public Object duplicateSymbol(IlvSDMModel model, Object node) {
    IlvSymbologyTreeViewActions actions = getNodeAction(model.getTag(node));
    if (actions != null) {
      Object duplicatedNode = actions.duplicateSymbol(model, node);
      setNodeAction(model.getTag(duplicatedNode), actions);
      return duplicatedNode;
    }
    return null;
  }

  /** {@inheritDoc}*/
  public void editSymbol(IlvSDMModel model, Object node, IlvApplyObject applier) {
    IlvSymbologyTreeViewActions actions = getNodeAction(model.getTag(node));
    if (actions != null) {
      actions.editSymbol(model, node, applier);
    }
  }

  /** {@inheritDoc}*/
  public void editSymbology(IlvSDMModel model, IlvApplyObject applier) {
    // not implemented
  }

  /** {@inheritDoc}*/
  public boolean isCreateSymbolEnabled(IlvSDMModel model) {
    for (int i = 0; i < actionTable.length; i++) {
      if (actionTable[i].isCreateSymbolEnabled(model)) {
        return true;
      }
    }
    return false;
  }

  /** {@inheritDoc}*/
  public boolean isDuplicateSymbolEnabled(IlvSDMModel model) {
    for (int i = 0; i < actionTable.length; i++) {
      if (actionTable[i].isDuplicateSymbolEnabled(model)) {
        return true;
      }
    }
    return false;
  }

  /** {@inheritDoc}*/
  public boolean isEditSymbolEnabled(IlvSDMModel model) {
    for (int i = 0; i < actionTable.length; i++) {
      if (actionTable[i].isEditSymbolEnabled(model)) {
        return true;
      }
    }
    return false;
  }

  /** {@inheritDoc}*/
  public boolean isEditSymbologyEnabled(IlvSDMModel model) {
    for (int i = 0; i < actionTable.length; i++) {
      if (actionTable[i].isEditSymbologyEnabled(model)) {
        return true;
      }
    }
    return false;
  }

  /** {@inheritDoc}*/
  public Object newSymbol(String tag) {
    for (int i = 0; i < actionTable.length; i++) {
      Object node = actionTable[i].newSymbol(tag);
      if (node != null) {
        setNodeAction(tag, actionTable[i]);
        return node;
      }
    }
    return null;
  }

  /**
   * {@inheritDoc}
   */
  Override
  public void setView(IlvSymbologyTreeView treeView) {
    super.setView(treeView);
    for (int i = 0; i < actionTable.length; i++) {
      actionTable[i].setView(treeView);
    }
  }

  /**
   * Returns the action attached to this tag.
   * @param tag symbol tag.
   * @return the action attached to this tag.
   */
  protected IlvSymbologyTreeViewActions getNodeAction(String tag) {
    return association.get(tag);
  }

  /**
   * Sets the action attached to this tag.
   * @param tag symbol tag.
   * @param action the action attached to this tag.
   */
  protected void setNodeAction(String tag, IlvSymbologyTreeViewActions action) {
    association.put(tag, action);
  }

  public IlvPersistentObject getPersistentContext() {
    IlvPersistentObject context[] = new IlvPersistentObject[actionTable.length];
    for (int i = 0; i < actionTable.length; i++) {
      context[i] = actionTable[i].getPersistentContext();
    }
    return new IlvTablePersistentContext(context);
  }

  public void setPersistentContext(IlvPersistentObject context) {
    if (context instanceof IlvTablePersistentContext) {
        IlvTablePersistentContext tableContext = (IlvTablePersistentContext) context;
      for (int i = 0; i < actionTable.length; i++) {
        if (tableContext.getContext()[i] != null) {
          actionTable[i].setPersistentContext(tableContext.getContext()[i]);
        }
      }
    }
  }
  public boolean isPropertyIgnored(IlvSDMModel model,Object node,String propertyName) {
    IlvSymbologyTreeViewActions actions = getNodeAction(model.getTag(node));
    if(actions!=null) {
      return actions.isPropertyIgnored(model,node,propertyName);
    }
    return false;
  }

}