/*
 * 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.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

import ilog.views.chart.IlvChart;
import ilog.views.chart.IlvChartRenderer;
import ilog.views.chart.data.IlvAbstractDataSet;
import ilog.views.chart.data.IlvAbstractDataSource;
import ilog.views.chart.data.IlvDataSet;
import ilog.views.chart.data.IlvDataSetProperty;
import ilog.views.chart.data.IlvDataSource;
import ilog.views.chart.renderer.IlvAreaChartRenderer;
import ilog.views.util.IlvProductUtil;

public class DataModelExtension extends JFrame {
  private static final String MATH = "Math";
  private static final String PHYSICS = "Physics";
  private static final String CHEMISTRY = "Chemistry";

  // ~ Constructors -----------------------------------------------------------

  public DataModelExtension() {
    super("DataModel Extension");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    init();
  }

  // ~ Methods ----------------------------------------------------------------

  private void init() {
    Container container = getContentPane();

    // Create the chart.
    IlvChart chart = createChart();
    List<Student> students = new ArrayList<DataModelExtension.Student>();
    Student student = new Student("John");
    student.setGrade(MATH, Integer.valueOf(1));
    student.setGrade(PHYSICS, Integer.valueOf(3));
    student.setGrade(CHEMISTRY, Integer.valueOf(2));
    students.add(student);
    student = new Student("Mary");
    student.setGrade(MATH, Integer.valueOf(2));
    student.setGrade(PHYSICS, Integer.valueOf(1));
    student.setGrade(CHEMISTRY, Integer.valueOf(1));
    students.add(student);
    student = new Student("Greg");
    student.setGrade(MATH, Integer.valueOf(3));
    student.setGrade(PHYSICS, Integer.valueOf(2));
    student.setGrade(CHEMISTRY, Integer.valueOf(3));
    students.add(student);

    University university = new University(students);
    String[] courses = new String[] { MATH, PHYSICS, CHEMISTRY };
    IlvDataSource ds = new GradeDataSource(university.getUnderGraduateList(), courses);

    IlvChartRenderer r = createRenderer();
    r.setDataSource(ds);
    chart.addRenderer(r);

    chart.getXScale().setCategory(ds.getDataSet(0), false);
    chart.getYAxis(0).setDataMin(0);

    container.add(chart, BorderLayout.CENTER);

    setSize(400, 330);
  }

  protected IlvChart createChart() {
    IlvChart chart = new IlvChart(IlvChart.RADAR);
    chart.setForeground(new Color(102, 102, 153));
    chart.setAntiAliasing(true);
    chart.setBackground(Color.white);
    chart.setOpaque(true);
    chart.getChartArea().setPlotBackground(new Color(255, 245, 235));
    return chart;
  }

  protected IlvChartRenderer createRenderer() {
    IlvAreaChartRenderer r = new IlvAreaChartRenderer();
    r.setAutoTransparency(true);
    return r;
  }

  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);

    SwingUtilities.invokeLater(new Runnable() {
      Override
      public void run() {
        DataModelExtension frame = new DataModelExtension();
        frame.setVisible(true);
      }
    });
  }

  // ~ Inner Classes ----------------------------------------------------------

  /** Represents a University */
  static class University {
    List<Student> graduate;

    public University(List<Student> graduate) {
      this.graduate = graduate;
    }

    /** Returns the list of undergraduate students */
    List<Student> getUnderGraduateList() {
      return graduate;
    }
  }

  /** Represents a Student */
  static class Student {
    String name;
    Map<String, Integer> grades = new HashMap<String, Integer>();

    public Student(String name) {
      this.name = name;
    }

    /** Returns the name of the student */
    String getName() {
      return name;
    }

    /** Returns the grade for the specified course */
    int getGrade(String course) {
      return grades.get(course).intValue();
    }

    public void setGrade(String course, Integer grade) {
      grades.put(course, grade);
    }
  }

  static class GradeDataSource extends IlvAbstractDataSource {
    private List<Student> students;

    public GradeDataSource(List<Student> students, String[] courses) {
      this.students = students;
      getDataSetList().setDataSets(createDataSets(courses));
    }

    private final Student getStudent(int idx) {
      return students.get(idx);
    }

    private IlvDataSet[] createDataSets(String[] courses) {
      IlvDataSet[] dataSets = new IlvDataSet[courses.length];
      for (int i = 0; i < courses.length; ++i)
        dataSets[i] = new DataSet(courses[i]);
      return dataSets;
    }

    private class DataSet extends IlvAbstractDataSet {
      private String course;

      DataSet(String course) {
        this.course = course;
        IlvDataSetProperty.setCategory(this, Double.valueOf(1));
      }

      /** Returns the name of the course */
      Override
      public String getName() {
        return course;
      }

      /** Returns the number of students */
      Override
      public int getDataCount() {
        return GradeDataSource.this.students.size();
      }

      /** Simply returns the student index */
      Override
      public double getXData(int idx) {
        return idx;
      }

      /** Returns the grade of the specified student */
      Override
      public double getYData(int idx) {
        return GradeDataSource.this.getStudent(idx).getGrade(course);
      }

      /** Returns the name of the specified student */
      Override
      public String getDataLabel(int idx) {
        return GradeDataSource.this.getStudent(idx).getName();
      }
    }
  }
}