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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;

import org.apache.myfaces.trinidad.component.core.data.CoreTable;

import bank.css.CSSBean;
import ilog.views.chart.IlvChart;
import ilog.views.chart.IlvChartRenderer;
import ilog.views.chart.IlvDataWindow;
import ilog.views.chart.data.IlvDataSetPoint;
import ilog.views.chart.data.IlvDefaultDataSet;
import ilog.views.chart.faces.servlet.IlvFacesChart;
import ilog.views.chart.renderer.IlvAreaChartRenderer;
import ilog.views.chart.renderer.IlvBarChartRenderer;
import ilog.views.chart.renderer.IlvSingleBarRenderer;
import ilog.views.faces.dhtml.event.FacesViewActionEvent;

/**
 * This class in the main application bean. It contains the other beans and
 * resources, the chart for example. All the JSF actions are declared in this
 * class.
 */
public class BankBean {

  /**
   * The bean that contains the CSS theme configuration.
   */
  private CSSBean css = new CSSBean();

  /**
   * A data model to build the chart and the data table.
   */
  private RawDataModel dataModel = new RawDataModel();

  /**
   * The chart to display in the web pages.
   */
  private IlvChart chart;

  /**
   * The data table component that displays the list of operations.
   */
  private CoreTable dataTable = new CoreTable();

  // private List dataTable = new ArrayList

  private final static int NB_VISIBLE_ROWS = 5;

  /**
   * The account number of the customer
   */
  private Object accountNumber = "53721812344";

  /**
   * The name of the customer.
   */
  private Object name = "John Smith";

  /**
   * The message displayed if the login failed.
   */
  private String errorMessage;

  /**
   * The locales registered on this bean.
   */
  private Map<String, Locale> locales = new HashMap<String, Locale>();

  /**
   * The currently selected display point.
   */
  private IlvDataSetPoint currentPoint = null;

  /**
   * Creates a new bean instance.
   */
  public BankBean() {
    initLocales();
    initChartComponent();
  }

  /**
   * Populates the locale list.
   */
  protected void initLocales() {
    locales.put("English", Locale.ENGLISH);
  }

  /**
   * Creates the chart component to be displayed by the chart views. There are
   * two renderers: - One which displays a polyline representing the balance. -
   * A second that displays bars, a bar representing an operation.
   */
  protected void initChartComponent() {
    chart = new IlvFacesChart();
    RawDataModel raw = new RawDataModel();
    IlvBarChartRenderer barRenderer = new IlvBarChartRenderer(IlvBarChartRenderer.SUPERIMPOSED);
    IlvAreaChartRenderer areaRenderer = new IlvAreaChartRenderer();
    IlvDefaultDataSet ds1 = new IlvDefaultDataSet("Balance", raw.getDates(), raw.getBalances(), false);
    ds1.setDataLabels(raw.getLabels());
    IlvDefaultDataSet ccDS = raw.getCcDS();
    IlvDefaultDataSet transferDS = raw.getTransferDS();
    IlvDefaultDataSet withdrawDS = raw.getWithdrawDS();
    IlvDefaultDataSet checkDS = raw.getCheckDS();
    areaRenderer.getDataSource().addDataSet(ds1);
    barRenderer.getDataSource().addDataSet(ccDS);
    barRenderer.getDataSource().addDataSet(transferDS);
    barRenderer.getDataSource().addDataSet(withdrawDS);
    barRenderer.getDataSource().addDataSet(checkDS);
    chart.addRenderer(areaRenderer);
    chart.addRenderer(barRenderer);
    Iterator<IlvChartRenderer> iter = barRenderer.getChildIterator();
    while (iter.hasNext())
      ((IlvSingleBarRenderer) iter.next()).setWidthPercent(90);

  }

  // Actions
  /**
   * Changes the current CSS theme.
   * 
   * @param evt
   *          The action event sent by the component.
   */
  public void changeTheme(ActionEvent evt) {
    String newTheme = evt.getComponent().getId();
    css.setTheme(newTheme);
  }

  /**
   * Changes the current locale.
   * 
   * @param evt
   *          The action event sent by the component.
   */
  public void changeLocale(ActionEvent evt) {
    String localeId = evt.getComponent().getId();
    FacesContext ctx = FacesContext.getCurrentInstance();
    Locale locale = (Locale) locales.get(localeId);
    ctx.getViewRoot().setLocale(locale);
    chart.setLocale(locale);
  }

  /**
   * Set the selected index on the index specified by the event value.
   * 
   * @param evt
   *          The value change event sent by the component.
   */
  public void selectedIndexChanged(ValueChangeEvent evt) {
    int newIndex = Integer.parseInt((String) evt.getNewValue());
    selectedIndexChanged(newIndex);
  }

  /**
   * Set the table selected index.
   * 
   * @param index
   *          The index of the selected point in the table model.
   */
  public void selectedIndexChanged(int index) {
    dataModel.setSelectedIndex(index);
  }

  /**
   * Shows on the table the operations visible on the chart.
   * 
   * @param event
   *          The action event.
   */
  public void syncTable(ActionEvent event) {
    IlvDataWindow win = getChart().getCoordinateSystem(0).getVisibleWindow();
    int[] indexes = dataModel.getVisibleIndexes(win);
    int length = indexes[1] - indexes[0] + 1;
    dataTable.setRows(length);
    dataTable.setFirst(dataModel.getRowCount() - indexes[1] - 1);
  }

  /**
   * Sets the table selected index according to the display point selected.
   * 
   * @param evt
   *          The value change event.
   */
  public void selectedDataPointChanged(ValueChangeEvent evt) {
    IlvDataSetPoint dataSetPoint = (IlvDataSetPoint) evt.getNewValue();
    selectDataSetPoint(dataSetPoint);
  }

  /**
   * Selects the specified data set point.
   * 
   * @param dataSetPoint
   *          The date set point to select.
   */
  public void selectDataSetPoint(IlvDataSetPoint dataSetPoint) {
    if (dataSetPoint != null && !dataSetPoint.equals(currentPoint)) {

      IlvChart chart = getChart();

      // Retrieve the list of the indexes table of the points in this data
      // set.
      SuppressWarnings("unchecked")
      List<Integer> list = (ArrayList<Integer>) dataSetPoint.getDataSet().getProperty("indexes");
      if (list != null) {

        chart.setPseudoClasses(dataSetPoint.getDataSet(), dataSetPoint.getIndex(), new String[] { "selected" });

        if (currentPoint != null) {

          getChart().removePseudoClass(currentPoint.getDataSet(), currentPoint.getIndex(), "selected");
        }

        int index = ((Integer) list.get(dataSetPoint.getIndex())).intValue();
        currentPoint = dataSetPoint;

        selectedIndexChanged(index);
      }
    }

  }

  /**
   * Sets the table selected index accoring to the display point selected.
   * 
   * @param evt
   */
  public void selectedDataPointChanged(FacesViewActionEvent evt) {
    IlvDataSetPoint dataSetPoint = (IlvDataSetPoint) evt.getObject();
    selectDataSetPoint(dataSetPoint);
  }

  /**
   * Displays the next <code>NB_VISIBLE_ROWS</code> rows of the operation table.
   * 
   * @param evt
   *          The action event.
   */
  public void previousTablePage(ActionEvent evt) {
    int first = dataTable.getFirst();
    first += NB_VISIBLE_ROWS;
    if (first >= dataModel.getRowCount())
      first = dataModel.getRowCount() - 1;
    dataTable.setFirst(first);
  }

  /**
   * Displays the previous <code>NB_VISIBLE_ROWS</code> rows of the operation
   * table.
   * 
   * @param evt
   *          The action event.
   */
  public void nextTablePage(ActionEvent evt) {
    int first = dataTable.getFirst();
    first -= NB_VISIBLE_ROWS;
    if (first < 0)
      first = 0;
    dataTable.setFirst(first);
  }

  /**
   * Changes the current CSS theme.
   * 
   * @param evt
   *          The value change event sent by the component.
   */
  public void changeCSS(ValueChangeEvent evt) {
    getCss().setTheme((String) evt.getNewValue());
  }

  /**
   * Sets the text to the chart header.
   * 
   * @param evt
   *          The vale change event.
   */
  public void setHeaderLabel(ValueChangeEvent evt) {
    chart.setHeaderText((String) evt.getNewValue());
  }

  /**
   * Sets the text to the chart footer.
   * 
   * @param evt
   *          The vale change event.
   */
  public void setFooterLabel(ValueChangeEvent evt) {
    chart.setFooterText((String) evt.getNewValue());
  }

  // Setters & Getters
  public CSSBean getCss() {
    return css;
  }

  public void setCss(CSSBean bean) {
    css = bean;
  }

  public Object getAccountNumber() {
    return accountNumber;
  }

  public Object getName() {
    return name;
  }

  public void setAccountNumber(Object object) {
    accountNumber = object;
  }

  public void setName(Object object) {
    name = object;
  }

  public String getErrorMessage() {
    return errorMessage;
  }

  public void setErrorMessage(String string) {
    errorMessage = string;
  }

  public RawDataModel getDataModel() {
    return dataModel;
  }

  public void setDataModel(RawDataModel model) {
    dataModel = model;
  }

  public IlvChart getChart() {
    return chart;
  }

  public void setChart(IlvChart chart) {
  }

  public CoreTable getDataTable() {
    return dataTable;
  }

  public void setDataTable(CoreTable data) {
    this.dataTable = data;
  }

}