/*
 * 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.
 */

import java.awt.Color;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.NumberFormat;
import com.ibm.icu.text.SimpleDateFormat;
import com.ibm.icu.util.ULocale;

import ilog.views.chart.IlvChart;
import ilog.views.chart.IlvChartRenderer;
import ilog.views.chart.IlvScale;
import ilog.views.chart.IlvStyle;
import ilog.views.chart.IlvTimeUnit;
import ilog.views.chart.IlvValueFormat;
import ilog.views.chart.data.IlvDataSet;
import ilog.views.chart.data.IlvDefaultDataSet;
import ilog.views.chart.renderer.IlvSingleBarRenderer;
import ilog.views.util.IlvProductUtil;
import ilog.views.util.time.IlvCalendarFactory;

/**
 * This example illustrates how to handle scales labels.
 */
public class ScaleLabelsExample {
  /**
   * An IlvValueFormat implementation to handle "time categories". A
   * CategoryTimeFormat is defined by:
   * <ul>
   * <li>a time origin, used to compute the date corresponding to an index.
   * <li>a time step, that defines the "unit" of the categories.
   * </ul>
   * This class format the scale labels such that a data point index is
   * converted into a date based on the CategoryTimeFormat origin and time step.
   * For example, if the origin is set to 01/01/2000 and the step is set to
   * <code>Calendar.YEAR</code>, then the index 0 is converted into 01/01/2000,
   * index 1 into 01/01/2001, index 2 into 01/01/2002, and so on.
   * <P>
   * Note: This class is particularly well suited for discrete time series (ie
   * time categories) when used in conjunction with a
   * <code>IlvDefaultStepsDefinition</code>. Indeed, a true time scale (that is
   * a scale using an <code>IlvTimeStepsDefinition</code> or upon which a time
   * step unit has been set) should only be used with continuous time series.
   */
  private static class CategoryTimeFormat implements IlvValueFormat {
    private int step;
    private Calendar cal;
    private SimpleDateFormat fmt;
    private Date origin;

    /**
     * Initialize a new <code>CategoryTimeFormat</code>.
     * 
     * @param origin
     *          The origin of the categories.
     * @param step
     *          The step of the categories. Should be a valid Calendar field
     *          value.
     * @param unit
     *          An optional time unit used to format the label. If null, the
     *          default format is used.
     * @param locale
     *          The locale for formatting.
     */
    public CategoryTimeFormat(Date origin, int step, IlvTimeUnit unit, ULocale locale) {
      this.origin = origin;
      this.step = step;
      this.cal = IlvCalendarFactory.createInstance(locale);
      this.fmt = (SimpleDateFormat) DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale);
      // set the format pattern, if specified.
      if (unit != null) {
        fmt = (SimpleDateFormat) fmt.clone();
        fmt.applyPattern(unit.getFormatString(locale.toLocale()));
      }
    }

    /**
     * Formats the specified value into a string.
     */
    Override
    public String formatValue(double value) {
      // compute the date corresponding to the given index.
      cal.setTime(origin);
      cal.add(step, (int) value);
      return fmt.format(cal.getTime());
    }
  }

  public static void main(String[] args) {
    // This sample uses JViews Charts features. When deploying an
    // application that includes this code, you need to be in possession
    // of a Perforce JViews Charts Deployment license.
    IlvProductUtil.DeploymentLicenseRequired(IlvProductUtil.JViews_Charts_Deployment);

    // the data series.
    final double[] yvalues = { 30, 80, 55, 91, 125, 53, 61, 98, 74, 61 };

    // creates the chart data model. It contains only one series.
    IlvDataSet dataSet = new IlvDefaultDataSet("Series A", yvalues);
    // creates a chart (cartesian by default). The graphical representation
    // is polyline by default.
    final IlvChart chart = new IlvChart();
    chart.setHeaderText("Average Precipitation");
    // Attach the data model to the chart and render it as Bar.
    IlvChartRenderer r = new IlvSingleBarRenderer();
    r.setStyles(new IlvStyle[] { new IlvStyle(new Color(249, 128, 114), new Color(183, 225, 204)) });
    chart.addRenderer(r, dataSet);
    // modify the y-axis data range so that it starts at 0.
    chart.getYAxis(0).setDataMin(0);

    // -- Handle scales labels.

    IlvScale xscale = chart.getXScale();
    // We set a CategoryTimeFormat on the x-scale to handle
    // the data point indices as "time category". Note that we do not use a
    // Time scale here because our values are discrete values (index) and not
    // continuous values.
    // The CategoryTimeFormat is initialized so that its origin is
    // January, 1st 1980 and its increment matches a year, using the
    // date format from the IlvTimeUnit.YEAR unit.
    // See above the documentation of the CategoryTimeFormat.
    Calendar cal = new GregorianCalendar();
    cal.set(1980, 0, 1);
    xscale.setLabelFormat(new CategoryTimeFormat(cal.getTime(), Calendar.YEAR, IlvTimeUnit.YEAR, chart.getULocale()));

    // We also set a custom IlvValueFormat on the y-scale so that labels
    // are displayed as: value + " cm".
    IlvScale yscale = chart.getYScale(0);
    yscale.setLabelFormat(new IlvValueFormat() {
      private NumberFormat numformat = NumberFormat.getInstance();

      Override
      public String formatValue(double value) {
        return numformat.format(value) + " cm";
      }
    });

    // The GUI.
    SwingUtilities.invokeLater(new Runnable() {
      Override
      public void run() {
        JFrame frame = new JFrame("Customizing Scales Labelling");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(chart);
        frame.setSize(400, 300);
        frame.setVisible(true);
      }
    });
  }
}