package com.desfate.chart;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.PointF;
import android.util.AttributeSet;

import com.desfate.chart.data.ChartLineColors;
import com.desfate.chart.entity.LineEntity;
import com.desfate.chart.entity.StickEntity;

import java.util.ArrayList;
import java.util.List;


/**
 * <p>
 * MinusStickChart is inherits from StickChart which its data can be minus value
 * </p>
 * <p>
 * MinusStickChartはグラフの一種です、マイナーデータをチャートで表示は可能です
 * </p>
 * <p>
 * MinusStickChart继承于StickChart的，可以在StickChart基础上绘制包含负数的柱状条。
 * </p>
 */
public class MinusStickChart extends StickChart {

    /**
     * <p>
     * Default price up stick's border color
     * </p>
     * <p>
     * 默认上方柱形的边框颜色
     * </p>
     */
    public static final int DEFAULT_POSITIVE_STICK_BORDER_COLOR = Color.RED;
    /**
     * <p>
     * Default price up stick's fill color
     * </p>
     * <p>
     * 默认上方柱形的填充颜色
     * </p>
     */
    public static final int DEFAULT_POSITIVE_STICK_FILL_COLOR = Color.RED;
    /**
     * <p>
     * Default price down stick's border color
     * </p>
     * <p>
     * 値下りローソクのボーダー色のデフォルト値
     * </p>
     * <p>
     * 默认下方柱形的边框颜色
     * </p>
     */
    public static final int DEFAULT_NEGATIVE_STICK_BORDER_COLOR = Color.GREEN;

    /**
     * 当价格持平时候柱子颜色
     */
    public static final int DEFAULT_CROSS_STAR_COLOR = Color.LTGRAY;
    /**
     * <p>
     * Default price down stick's fill color
     * </p>
     * <p>
     * 値下りローソクの色のデフォルト値
     * </p>
     * <p>
     * 默认下方柱形的填充颜色
     * </p>
     */
    public static final int DEFAULT_NEGATIVE_STICK_FILL_COLOR = Color.GREEN;
    /**
     * <p>
     * Price up stick's border color
     * </p>
     * <p>
     * 値上がりローソクのボーダー色
     * </p>
     * <p>
     * 上方柱形的边框颜色
     * </p>
     */
    private int positiveStickBorderColor = DEFAULT_POSITIVE_STICK_BORDER_COLOR;
    /**
     * <p>
     * Price up stick's fill color
     * </p>
     * <p>
     * 上方柱形的填充颜色
     * </p>
     */
    private int positiveStickFillColor = DEFAULT_POSITIVE_STICK_FILL_COLOR;
    /**
     * <p>
     * Price down stick's border color
     * </p>
     * <p>
     * 下方柱形的边框颜色
     * </p>
     */

    private int negativeStickBorderColor = /*DEFAULT_NEGATIVE_STICK_BORDER_COLOR*/0xFF009933;
    /**
     * <p>
     * Price down stick's fill color
     * </p>
     * <p>
     * 下方柱形的填充颜色
     * </p>
     */
    private int negativeStickFillColor = /*DEFAULT_NEGATIVE_STICK_FILL_COLOR*/0xFF009933;

    /**
     * <p>
     * Price no change stick's color (cross-star,T-like etc.)
     * </p>
     * <p>
     * クローススターの色（価格変動無し）
     * </p>
     * <p>
     * 十字线显示颜色（十字星,一字平线,T形线的情况）
     * </p>
     */
    private int crossStarColor = DEFAULT_CROSS_STAR_COLOR;
    /**
     * <p>
     * data to draw lines
     * </p>
     * <p>
     * ラインを書く用データ
     * </p>
     * <p>
     * 绘制线条用的数据
     * </p>
     */
    private List<LineEntity> lineData = null;
    private List<LineEntity> newLineData = null;

    /**
     * 是否显示stick图形
     */
    private boolean showStick = true;

    private boolean isChangeLineData = false;

    private int tickStartIndex = 0;

    /*
     * (non-Javadoc)
     *
     * @param context
     *
     */
    public MinusStickChart(Context context) {
        super(context);
    }

    /*
     * (non-Javadoc)
     *
     * @param context
     *
     * @param attrs
     *
     * @param defStyle
     *
     * AttributeSet, int)
     */
    public MinusStickChart(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    /*
     * (non-Javadoc)
     *
     * @param context
     *
     * @param attrs
     *
     * AttributeSet)
     */
    public MinusStickChart(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onUpdate() {
        updateLineData();
        super.onUpdate();
    }

    /**
     * @param crossStarColor the crossStarColor to set
     */
    public void setCrossStarColor(int crossStarColor) {
        this.crossStarColor = crossStarColor;
    }

    public int getCrossStarColor() {
        return crossStarColor;
    }

    @Override
    protected void drawChart(Canvas canvas) {
        super.drawChart(canvas);
        // draw lines
        if (null != this.getLineData()) {
            if (0 != this.getLineData().size()) {
                drawLines(canvas);
            }
        }
    }

    @Override
    protected void initMaxAndMin() {
        super.initMaxAndMin();
        // calculate max value and min value
        if (null != this.getLineData()) {
            for (int i = 0; i < getLineData().size(); i++) {
                LineEntity line = getLineData().get(i);
                if (line.isDisplay()) {
                    List<Double> lineData = line.getLineData();

                    if (lineData != null) {

                        for (int j = this.getStartIndex(); j >= 0 && j < lineData.size() && j < this.getStartIndex() + this.getMaxSticksNum(); j++) {
                            float value = lineData.get(j).floatValue();
                            if (value > maxValue) {
                                maxValue = value;
                            } else if (value < minValue) {
                                minValue = value;
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * <p>
     * 实际绘制的柱宽
     * </p>
     */
    @Override
    protected float getItemShowWidth() {
        return super.getItemWidth() - 6f;
    }

    /*
     * (non-Javadoc)
     *
     * @param canvas
     *
     *
     *
     */
    @Override
    protected void drawSticks(Canvas canvas) {
        // stick width
        float stickWidth = getItemWidth();
        float stickShowWidth = getItemShowWidth();
        float stickShowOffset = (stickWidth - stickShowWidth) / 2;
        // start point's X
        float stickX = /*super.getAxisMarginLeft() + super.getAxisMarginRight()*/2f;

        Paint mPaintPositiveFill = new Paint();
        mPaintPositiveFill.setStyle(Style.FILL);
        mPaintPositiveFill.setStrokeWidth(2.0f);
        mPaintPositiveFill.setColor(positiveStickFillColor);

        Paint mPaintPositiveBorder = new Paint();
        mPaintPositiveBorder.setStyle(Style.STROKE);
        mPaintPositiveBorder.setStrokeWidth(2.0f);
        mPaintPositiveBorder.setColor(positiveStickBorderColor);

        Paint mPaintNegativeFill = new Paint();
        mPaintNegativeFill.setStyle(Style.FILL);
        mPaintNegativeFill.setColor(negativeStickFillColor);

        Paint mPaintNegativeBorder = new Paint();
        mPaintNegativeBorder.setStyle(Style.STROKE);
        mPaintNegativeBorder.setStrokeWidth(2.0f);
        mPaintNegativeBorder.setColor(negativeStickBorderColor);

        Paint sameFill = new Paint();
        sameFill.setStyle(Style.FILL);
        sameFill.setColor(crossStarColor);

        Paint sameBorder = new Paint();
        sameBorder.setStyle(Style.STROKE);
        sameBorder.setStrokeWidth(2.0f);
        sameBorder.setColor(crossStarColor);

        List<StickEntity> data = super.getStickData();

        if (null != data) {

            int minIndex = data.size() - this.getMaxSticksNum();
            if (this.getStartIndex() > minIndex && minIndex > 0) {
                setStartIndex(minIndex);
            }
            if (!isShowStick()) {
                return;
            }
            Paint mPaint = new Paint();
            mPaint.setColor(ChartLineColors.BORDERCOLOR);
            float startY = (float) ((1f - (0 - super.minValue) * 10000000
                    / ((maxValue - minValue) * 10000) / 1000)
                    * (super.getHeight() - super.getAxisMarginBottom() - 2 * super.getAxisMarginTop()) + super.getAxisMarginTop());
//			float maxY = (float) ((1f - (maxValue - super.minValue)*10000000
//					/ ((maxValue - minValue)*10000)/1000)
//					* (super.getHeight() - super.getAxisMarginBottom() - 2*super.getAxisMarginTop()) + super.getAxisMarginTop());
//			float minY = (float) ((1f - (minValue - super.minValue)*10000000
//					/ ((maxValue - minValue)*10000)/1000)
//					* (super.getHeight() - super.getAxisMarginBottom() - 2*super.getAxisMarginTop()) + super.getAxisMarginTop());
            canvas.drawLine(2f, startY, super.getWidth() - super.getAxisMarginLeft(), startY, mPaint);
//			canvas.drawLine(getClickPostX(), maxY, getClickPostX(), minY, mPaint);
            // display as stick or line
            for (int i = this.getStartIndex(); i >= 0 && i < data.size() && i < this.getStartIndex() + this.getMaxSticksNum(); i++) {

                StickEntity e = data.get(i);

                float highY = (float) ((1f - (e.getHigh() - super.minValue) * 10000000
                        / ((maxValue - minValue) * 10000) / 1000)
                        * (super.getHeight() - super.getAxisMarginBottom() - 2 * super.getAxisMarginTop()) + super.getAxisMarginTop());
                float lowY = (float) ((1f - (e.getLow() - minValue) * 10000000
                        / ((maxValue - minValue) * 10000) / 1000)
                        * (super.getHeight() - super.getAxisMarginBottom() - 2 * super.getAxisMarginTop()) + super.getAxisMarginTop());

                // draw stick
                float left = stickX + stickShowOffset;
                if (lineData.size() > 1) {
                    if (e.getColorFlag() < -1) {
                        if (e.getLow() >= 0) {
                            canvas.drawRect(left, highY, left + stickShowWidth, lowY, mPaintPositiveFill);
                            canvas.drawRect(left, highY, left + stickShowWidth, lowY, mPaintPositiveBorder);
                        } else {
                            canvas.drawRect(left, highY, left + stickShowWidth, lowY, mPaintNegativeFill);
                            canvas.drawRect(left, highY, left + stickShowWidth, lowY, mPaintNegativeBorder);
                        }
                    }
                    if (e.getColorFlag() > 0) {
                        canvas.drawRect(left, highY, left + stickShowWidth, lowY,
                                mPaintPositiveFill);
                        canvas.drawRect(left, highY, left + stickShowWidth, lowY,
                                mPaintPositiveBorder);
                    } else if (e.getColorFlag() == 0) {
                        canvas.drawRect(left, highY, left + stickShowWidth, lowY,
                                sameFill);
                        canvas.drawRect(left, highY, left + stickShowWidth, lowY,
                                sameBorder);
                    } else if (e.getColorFlag() == -1) {
                        canvas.drawRect(left, highY, left + stickShowWidth, lowY,
                                mPaintNegativeFill);
                        canvas.drawRect(left, highY, left + stickShowWidth, lowY,
                                mPaintNegativeBorder);
                    }
                }
                // next x
                stickX = stickX + stickWidth;
            }
        }
    }

    /**
     * <p>
     * draw lines
     * </p>
     * <p>
     * ラインを書く
     * </p>
     * <p>
     * 绘制线条
     * </p>
     *
     * @param canvas
     */
    protected void drawLines(Canvas canvas) {
        // distance between two points
        float lineLength = getItemWidth();
        // start point‘s X
        float startX;

        // draw MA lines
        for (int i = 0; i < getLineData().size(); i++) {
            LineEntity line = getLineData().get(i);
            if (line.isDisplay()) {
                Paint mPaint = new Paint();
                mPaint.setColor(line.getLineColor());
                mPaint.setAntiAlias(true);
                mPaint.setStrokeWidth(2.0f);
                List<Double> lineData = line.getLineData();
                // set start point’s X
//				startX = /*super.getAxisMarginLeft() + super.getAxisMarginRight()*/2f;
                startX = lineLength / 2f;
                // start point
                PointF ptFirst = null;
                if (lineData != null) {

                    for (int j = this.getStartIndex(); j >= 0 && j < lineData.size() && j < this.getStartIndex() + this.getMaxSticksNum(); j++) {

                        float value = lineData.get(j).floatValue();
                        // calculate Y
                        float valueY = super.getAxisMarginTop() + (float) ((1f -
                                (value - super.getMinValue()) * 10000000 / ((super.getMaxValue() - super.getMinValue()) * 10000) / 1000) *
                                (super.getHeight() - super.getAxisMarginBottom() - 2 * super.getAxisMarginTop()));

//						if (lineEntityData.getLineData().size() == 1) {//FIXME : old(现在只支持rsi14，前面14个周期不画线)
//							if (j > 13) {
//								if (j > this.getStartIndex()) {
//									canvas.drawLine(ptFirst.x, ptFirst.y, startX,
//											valueY, mPaint);
//								}
//							}
//						} else {
//							if (j > this.getStartIndex()) {
//								canvas.drawLine(ptFirst.x, ptFirst.y, startX,
//										valueY, mPaint);
//							}
//						}

                        if (j >= line.getStartIndex()) {//FIXME : 设置了画线位置
                            if (j > this.getStartIndex()) {
                                canvas.drawLine(ptFirst.x, ptFirst.y, startX,
                                        valueY, mPaint);
                            }
                        }

                        // reset
                        ptFirst = new PointF(startX, valueY);
                        startX = startX + lineLength;
                    }
                }
            }
        }
    }

    public void updateLineData() {
        if (isChangeLineData) {
            isChangeLineData = false;
            if (this.newLineData != null) {

                if (this.lineData == null) {
                    lineData = new ArrayList<LineEntity>();
                }
                this.lineData.clear();
                this.lineData.addAll(newLineData);
            }
        }
    }

    /**
     * @return the lineData
     */
    public List<LineEntity> getLineData() {

        if (lineData == null) {
            lineData = new ArrayList<LineEntity>();
        }
        return lineData;
    }

    public List<LineEntity> getNewLineData() {

        if (newLineData == null) {
            newLineData = new ArrayList<LineEntity>();
        }
        return newLineData;
    }

    /**
     * @param lineData the lineData to set
     */
    public void setLineData(List<LineEntity> lineData) {
        if (this.newLineData == null) {
            this.newLineData = new ArrayList<LineEntity>();
        }
        this.newLineData.clear();
        this.newLineData.addAll(lineData);
        isChangeLineData = true;
    }

    /**
     * @return the positiveStickBorderColor
     */
    public int getPositiveStickBorderColor() {
        return positiveStickBorderColor;
    }

    /**
     * @param positiveStickBorderColor the positiveStickBorderColor to set
     */
    public void setPositiveStickBorderColor(int positiveStickBorderColor) {
        this.positiveStickBorderColor = positiveStickBorderColor;
    }

    /**
     * @return the positiveStickFillColor
     */
    public int getPositiveStickFillColor() {
        return positiveStickFillColor;
    }

    /**
     * @param positiveStickFillColor the positiveStickFillColor to set
     */
    public void setPositiveStickFillColor(int positiveStickFillColor) {
        this.positiveStickFillColor = positiveStickFillColor;
    }

    /**
     * @return the negativeStickBorderColor
     */
    public int getNegativeStickBorderColor() {
        return negativeStickBorderColor;
    }

    /**
     * @param negativeStickBorderColor the negativeStickBorderColor to set
     */
    public void setNegativeStickBorderColor(int negativeStickBorderColor) {
        this.negativeStickBorderColor = negativeStickBorderColor;
    }

    /**
     * @return the negativeStickFillColor
     */
    public int getNegativeStickFillColor() {
        return negativeStickFillColor;
    }

    /**
     * @param negativeStickFillColor the negativeStickFillColor to set
     */
    public void setNegativeStickFillColor(int negativeStickFillColor) {
        this.negativeStickFillColor = negativeStickFillColor;
    }

    public int getTickStartIndex() {
        return tickStartIndex;
    }

    public void setTickStartIndex(int tickStartIndex) {
        this.tickStartIndex = tickStartIndex;
    }

    public boolean isShowStick() {
        return showStick;
    }

    public void setShowStick(boolean showStick) {
        this.showStick = showStick;
    }

}
