/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2006/11/20 13:41:38
!  AUTHOR(S): KOGA, Junichiro
!  File : SeriesInfo.java
!  
!  Contact address :  Phase System Consortium
!                     E-mail: phase_system@nims.go.jp URL https://azuma.nims.go.jp
!
!
!   Since 2002, this program set had been intensively developed as a part of the following 
!  national projects supported by the Ministry of Education, Culture, Sports, Science and
!  Technology (MEXT) of Japan; "Frontier Simulation Software for Industrial Science
!  (FSIS)" from 2002 to 2005, "Revolutionary Simulation Software (RSS21)" from 2006 to
!  2008. "Research and Development of Innovative Simulation Software (RISS)" from 2008
!  to 2013. These projects is lead by the Center for Research on Innovative Simulation 
!  Software (CISS), the Institute of Industrial Science (IIS), the University of Tokyo.
!   Since 2013, this program set has been further developed centering on PHASE System
!  Consortium. 
!   The activity of development of this program set has been supervised by Takahisa Ohno.
!
!=======================================================================
 */
package ciss.phase_viewer.graph.plotattributes;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Stroke;

import org.apache.log4j.Logger;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;

/**
 * Seriesの指定に必要な情報を保持する.
 */
public class SeriesInfo {
    private Logger logger = Logger.getLogger(SeriesInfo.class.getName());

    public static int LINE = 0;

    public static int SHAPE = 1;

    public static int LINE_AND_SHAPE = 2;

    private XYPlot xyplot;

    private Color color;

    private int plottype = 0;

    private int linetype = 0;

    private int shapetype = 0;

    private int index;

    private float linewidth = -1.f;

    private double shapesize = -1.d;

    /**
     * @param xyplot
     *            扱いたいSeriesと関連付けられたXYPlotオブジェクト
     * @param index
     *            何番目のSeriesなのかを指定.
     */
    public SeriesInfo(XYPlot xyplot, int index) {
        this.xyplot = xyplot;
        this.index = index;
        init();
    }

    /**
     * 指定のSeriesInfoをコピーして初期化する.
     * 
     * @param info
     */
    public SeriesInfo(SeriesInfo info) {
        copy(info);
    }

    private void init() {
        XYItemRenderer renderer = xyplot.getRenderer();
        color = (Color) renderer.getSeriesPaint(index);
        Stroke stroke = renderer.getBaseStroke();
        if (stroke instanceof BasicStroke) {
            linewidth = ((BasicStroke) stroke).getLineWidth();
        }
        shapesize = renderer.getBaseShape().getBounds().width;
    }

    /**
     * プロット種をセット. 線か点か両方か, など.
     * 
     * @param plottype
     *            プロット種.
     */
    public void setPlotType(int plottype) {
        this.plottype = plottype;
    }

    /**
     * 線種の指定
     * 
     * @param linetype
     *            線種を指定.
     */
    public void setLineType(int linetype) {
        this.linetype = linetype;
    }

    /**
     * shapeプロットをする際に, shapeの形状を指定.
     * 
     * @param shapetype
     *            「shape種」
     */
    public void setShapeType(int shapetype) {
        this.shapetype = shapetype;
    }

    /**
     * 線幅を定義.
     * 
     * @param linewidth
     *            線幅
     */
    public void setLineWidth(float linewidth) {
        this.linewidth = linewidth;
    }

    /**
     * 「形」の大きさを定義
     * 
     * @param shapesize
     *            形の大きさ.
     */
    public void setShapeSize(double shapesize) {
        this.shapesize = shapesize;
    }

    /**
     * このSeriesの描画色を指定.
     * 
     * @param color
     *            指定したいSeriesの色
     */
    public void setColor(Color color) {
        this.color = color;
    }

    /**
     * ここで設定したColorを返す.
     * 
     * @return color
     */
    public Color getColor() {
        return color;
    }

    /**
     * 「プロット種」の取得.
     * 
     * @return プロット種
     */
    public int getPlotType() {
        return plottype;
    }

    /**
     * 線の記述方法の取得
     * 
     * @return 線の記述方法
     */
    public int getLineType() {
        return linetype;
    }

    /**
     * 点種の取得
     * 
     * @return 点種
     */
    public int getShapeType() {
        return shapetype;
    }

    /**
     * 線幅の取得
     * 
     * @return 線幅
     */
    public float getLineWidth() {
        return linewidth;
    }

    /**
     * 点の大きさを取得.
     * 
     * @return 点の大きさ
     */
    public double getShapeSize() {
        return shapesize;
    }

    public String toString() {
        return "index: " + index + " color: " + color + " plottype: "
                + plottype + " linetype: " + linetype + " shapetype: "
                + shapetype + " linewidth: " + linewidth + " shapesize: "
                + shapesize;
    }

    public void copy(SeriesInfo info) {
        this.color = info.getColor();
        this.linetype = info.getLineType();
        this.linewidth = info.getLineWidth();
        this.plottype = info.getPlotType();
        this.shapesize = info.getShapeSize();
        this.shapetype = info.getShapeType();
    }

    /**
     * このSeriesに関連付けられたXYPlotを, 指定のrendererのインデックスを利用して更新.
     * 
     * @param rendererIndex
     *            レンダラーのインデックス
     * @return うまく行かない場合false
     */
    public boolean update(int rendererIndex) {
        return update(this.xyplot, rendererIndex, index);
    }

    /**
     * このSeriesを元に, 指定のXYPlotを更新する.
     * 
     * @param xyPlot
     *            更新したいXYPlot.
     * @return うまく行かない場合false
     */
    public boolean update(XYPlot xyPlot) {
        return update(xyPlot, 0, 0);
    }

    /**
     * このSeriesを元に, 指定のXYPlotを更新する.
     * 
     * @param xyPlot
     *            更新したいXYPlot.
     * @param rendererIndex
     *            更新したいシリーズのレンダラーのインデックス
     * @return うまくいかない場合false
     */
    public boolean update(XYPlot xyPlot, int rendererIndex) {
        return update(xyPlot, rendererIndex, index);
    }

    /**
     * このSeriesInfoを元に指定のXYPlotを更新する.
     * 
     * @param xyPlot
     *            更新したいXYPlot.
     * @param rendererIndex
     *            レンダラーのインデックス. デフォルト: 0
     * @param 対応するSeriesのインデックス
     *            . デフォルト: 0
     * @return うまく行かない場合false
     */
    public boolean update(XYPlot xyPlot, int rendererIndex, int seriesIndex) {
        StandardXYItemRenderer srenderer = null;
        if (xyplot.getRenderer(rendererIndex) instanceof StandardXYItemRenderer) {
            logger.debug("rendererIndex: " + rendererIndex);
            srenderer = (StandardXYItemRenderer) xyplot
                    .getRenderer(rendererIndex);
        } else {
            logger.error("invalid renderer.");
            return false;
        }

        logger.debug(this);
        float linewidth = this.getLineWidth();
        double shapesize = this.getShapeSize();

        srenderer.setDrawSeriesLineAsPath(true);
        if (this.getPlotType() == LINE) {
            shapesize = 0.0d;
            srenderer.setBaseShapesVisible(false);
            srenderer.setPlotLines(true);
        } else if (this.getPlotType() == SHAPE) {
            linewidth = -1.f;
            srenderer.setBaseShapesVisible(true);
            srenderer.setPlotLines(false);
        } else if (this.getPlotType() == LINE_AND_SHAPE) {
            srenderer.setBaseShapesVisible(true);
            srenderer.setPlotLines(true);
        }

        logger.debug("line width, shape size: " + linewidth + ", " + shapesize);

        PlotShapesAndLines psal = new PlotShapesAndLines();
        srenderer.setShapesFilled(true);
        srenderer.setSeriesPaint(seriesIndex, this.getColor());
        srenderer.setSeriesShape(seriesIndex,
                psal.getShape(this.getShapeType(), shapesize));
        srenderer.setSeriesStroke(seriesIndex,
                psal.getLine(this.getLineType(), linewidth));
        xyplot.setRenderer(rendererIndex, srenderer);

        return true;
    }
}
