/*
 * 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 treemap;

import java.awt.Point;
import java.awt.Rectangle;

import ilog.views.chart.IlvChart;
import ilog.views.chart.IlvChartDataPicker;
import ilog.views.chart.IlvDataInterval;
import ilog.views.chart.IlvDataWindow;
import ilog.views.chart.IlvDisplayObjectArea;
import ilog.views.chart.data.IlvDataSetPoint;
import ilog.views.chart.faces.dhtml.interactor.IlvChartObjectSelectedFinder;

/**
 * A chart object selected finder that returns the tree path of the picked
 * element of the treemap.
 */
public class TreemapPathFinder extends IlvChartObjectSelectedFinder {

  private IlvChartDataPicker dataPicker;

  private boolean isDoubleParamValid(String param) {
    return param != null && param != "";
  }

  private IlvDataWindow getRequestedVisibleWindow(IlvChart chart, String[] params) {
    IlvDataInterval xRange = chart.getXAxis().getVisibleRange();
    IlvDataInterval yRange = chart.getYAxis(0).getVisibleRange();
    IlvDataWindow dw = new IlvDataWindow(new IlvDataInterval(xRange), new IlvDataInterval(yRange));

    IlvDataInterval newXRange = dw.xRange;
    IlvDataInterval newYRange = dw.yRange;

    if (isDoubleParamValid(params[2]))
      newXRange.min = Double.valueOf(params[2]).doubleValue();
    if (isDoubleParamValid(params[3]))
      newXRange.max = Double.valueOf(params[3]).doubleValue();
    if (isDoubleParamValid(params[4]))
      newYRange.min = Double.valueOf(params[4]).doubleValue();
    if (isDoubleParamValid(params[5]))
      newYRange.max = Double.valueOf(params[5]).doubleValue();

    return dw;
  }

  private static boolean isTranslation(double delta, double newv, double oldv) {
    return (delta >= newv - oldv - 1E-9) && (delta <= newv - oldv + 1E-9);
  }

  private void prepareVisibleWindow(IlvChart chart, String[] params) {

    IlvDataWindow dw = getRequestedVisibleWindow(chart, params);

    IlvDataInterval xRange = chart.getXAxis().getVisibleRange();
    IlvDataInterval yRange = chart.getYAxis(0).getVisibleRange();
    IlvDataInterval newXRange = dw.xRange;
    IlvDataInterval newYRange = dw.yRange;
    double deltax = newXRange.max - xRange.max;
    double deltay = newYRange.max - yRange.max;
    if ((deltax != 0 && isTranslation(deltax, newXRange.min, xRange.min))
        && (deltay != 0 && isTranslation(deltay, newYRange.min, yRange.min))) {
      chart.scroll(deltax, deltay, 0);
    } else if (!newXRange.equals(xRange) || !newYRange.equals(yRange)) {
      chart.zoom(new IlvDataWindow(newXRange, newYRange), 0);
    }
  }

  private IlvChartDataPicker getDataPicker(int x, int y) {
    if (dataPicker == null)
      return createDataPicker(x, y);
    return dataPicker;
  }

  Override
  public Object computeObjectSelected(IlvChart chart, String[] params, String chartId) {
    if (chart == null)
      return null;

    Object res = null;

    int width = Integer.parseInt(params[6]);
    int height = Integer.parseInt(params[7]);

    IlvChart.IlvChartPaintContext context = new IlvChart.IlvChartPaintContext(width, height, chart);

    synchronized (chart.getLock()) {
      chart.startSession(context);

      prepareVisibleWindow(chart, params);

      int xpos = Integer.parseInt(params[0]);
      int ypos = Integer.parseInt(params[1]);

      Rectangle rect = (Rectangle) context.getBounds().get(chart.getChartArea());

      Point pt = new Point(xpos, ypos);
      Point ptTranslated = new Point(pt.x - rect.x, pt.y - rect.y);

      IlvDataSetPoint dsp = null;
      if (getMode() == ITEM_PICKING)
        dsp = chart.getDisplayItem(getDataPicker(ptTranslated.x, ptTranslated.y));
      else
        dsp = chart.getNearestPoint(getDataPicker(ptTranslated.x, ptTranslated.y));

      IlvDisplayObjectArea da = (IlvDisplayObjectArea) dsp;
      res = da != null ? da.getPath() : null;

      chart.endSession(context);
    }

    return res;
  }
}