/*
 * Licensed Materials - Property of Perforce Software, Inc. 
 * © Copyright Perforce Software, Inc. 2014, 2021 
 * © 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 interactor;

import java.awt.event.MouseEvent;

import ilog.views.chart.IlvChartDataPicker;
import ilog.views.chart.IlvChartInteractor;
import ilog.views.chart.IlvChartRenderer;
import ilog.views.chart.IlvDefaultChartDataPicker;
import ilog.views.chart.IlvDisplayPoint;

/**
 * The abstract base class for chart data manipulation.
 * This class provides an interface for querying information about the data in
 * a chart according to a given {@link IlvChartDataPicker}.
 * @see ilog.views.chart.IlvChartInteractor
 */
public abstract class IlvChartDataInteractor extends IlvChartInteractor {

  // ===================== Customization, Bean Properties =====================

  /**
   * The sensitivity used by the default data picker.
   */
  static final int EPSILON = 5;

  // -------------------------------------------------------------------------

  /**
   * The constant describing the precise item picking mode.
   * @see #setPickingMode
   * @see ilog.views.chart.IlvChart#getDisplayItem
   * 
   */
  public static final int ITEM_PICKING         = 1;

  /**
   * The constant describing the nearest item picking mode.
   * @see #setPickingMode
   * @see ilog.views.chart.IlvChart#getNearestItem
   * 
   */
  public static final int NEARESTITEM_PICKING  = 3;

  /**
   * The constant describing the nearest point picking mode.
   * @see #setPickingMode
   * @see ilog.views.chart.IlvChart#getNearestPoint
   */
  public static final int NEARESTPOINT_PICKING = 2;

  private int _pickingMode = NEARESTPOINT_PICKING;

  /**
   * Returns the picking mode.
   * @see #setPickingMode
   */
  public final int getPickingMode()
  {
    return _pickingMode;
  }

  /**
   * Sets the interactor picking mode. The picking mode defines how a
   * point is retrieved by the <code>pickData()</code> method.
   * If the mode is <code>ITEM_PICKING</code>, the display point is retrieved
   * by calling {@link ilog.views.chart.IlvChart#getDisplayItem}.
   * If the mode is <code>NEARESTITEM_PICKING</code>, the display point is
   * retrieved by calling {@link ilog.views.chart.IlvChart#getNearestItem}.
   * If the mode is <code>NEARESTPOINT_PICKING</code>, the display point is
   * retrieved by calling {@link ilog.views.chart.IlvChart#getNearestPoint}.
   * The default value is <code>NEARESTPOINT_PICKING</code>.
   * @see #ITEM_PICKING
   * @see #NEARESTITEM_PICKING
   * @see #NEARESTPOINT_PICKING
   * @see #pickData
   * 
   */
  public void setPickingMode(int mode)
  {
    switch (mode) {
      case ITEM_PICKING:
      case NEARESTITEM_PICKING:
      case NEARESTPOINT_PICKING:
        break;
      default:
        throw new IllegalArgumentException("invalid mode: "+mode);
    }
    _pickingMode = mode;
  }


  // ========================== Overridable behavior ==========================

  /**
   * An <code>IlvDefaultChartDataPicker</code> subclass which filters the
   * renderers according to the interactor y-axis index.
   */
  public class DataPicker extends IlvDefaultChartDataPicker
  {
    /**
     * Creates a new <code>IlvChartDataInteractor.DataPicker</code> object.
     */
    public DataPicker(int pickX, int pickY, int pickDist)
    {
      super(pickX, pickY, pickDist);
    }

    /**
     * Tells whether the specified renderer must be considered, when
     * searching among several renderers. The default implementation
     * returns <code>true</code> if the specified renderer and this
     * interactor are associated with the same y-axis.
     */
    Override
    public boolean accept(IlvChartRenderer r)
    {
      return IlvChartDataInteractor.this.getYAxisIndex() == r.getYAxisIdx();
    }
  }

  /**
   * Creates a new <code>IlvChartDataPicker</code> object. By default returns
   * an instance of <code>IlvChartDataInteractor.DataPicker</code>. This
   * method is called by {@link #pickData(MouseEvent)}.
   * @see ilog.views.chart.IlvDefaultChartDataPicker
   */
  protected IlvChartDataPicker createDataPicker(MouseEvent event)
  {
    return new DataPicker(event.getX(), event.getY(), EPSILON);
  }

  /**
   * Returns a display point corresponding to this picking event
   * that fulfills the default data picker criteria. This method
   * calls {@link #pickData(IlvChartDataPicker)}.
   */
  protected final IlvDisplayPoint pickData(MouseEvent event)
  {
    return pickData(createDataPicker(event));
  }

  /**
   * Returns a display point depending on the given data picker and the
   * current picking mode.
   * @see ilog.views.chart.IlvChartDataPicker
   * @see #setPickingMode
   */
  protected IlvDisplayPoint pickData(IlvChartDataPicker picker)
  {
    switch (getPickingMode()) {
      case ITEM_PICKING:
        return getChart().getDisplayItem(picker);
      case NEARESTITEM_PICKING:
        return getChart().getNearestItem(picker, null);
      case NEARESTPOINT_PICKING:
        return getChart().getNearestPoint(picker);
      default:
        return null;
    }
  }


  // ============================= Constructors =============================

  /**
   * Creates a new <code>IlvChartDataInteractor</code> object associated
   * with the given axis with the given action key event mask.
   */
  public IlvChartDataInteractor(int yAxisIndex, int eventMask)
  {
    super(yAxisIndex, eventMask);
  }

}