package com.desfate.chart;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;

import com.desfate.chart.entity.OHLCEntity;
import com.desfate.chart.event.ITouchEventNotify;

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

/**
 * <p>
 * CandleStickChart is a kind of graph that draw the OHLCs on a GridChart if you
 * want display some moving average lines on this graph, please use see
 * MACandleStickChart for more information
 * </p>
 * <p>
 * CandleStickChartはGridChartの表面でロウソクを書いたラインチャードです。移動平均線など
 * 分析線がお使いしたい場合、MACandleStickChartにご参照ください。
 * </p>
 * <p>
 * CandleStickChart是在GridChart上绘制K线（蜡烛线）的图表、如果需要支持显示均线，请参照 MACandleStickChart。
 * </p>
 *
 * @see CandleStickChart
 * @see MACandleStickChart
 */
public class CandleStickChart extends GridChart {

    private static final String TAG = "CandleStickChart";

    /**
     * <p>
     * Default price up stick's border color
     * </p>
     * <p>
     * 値上がりローソクのボーダー色のデフォルト値
     * </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>
     * <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;

    /**
     * <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>
     * Default price no change stick's color (cross-star,T-like etc.)
     * </p>
     * <p>
     * クローススターの色のデフォルト値
     * </p>
     * <p>
     * 默认十字线显示颜色
     * </p>
     */
    public static final int DEFAULT_CROSS_STAR_COLOR = Color.LTGRAY;

    /**
     * <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>
     * <p>
     * 阳线的填充颜色
     * </p>
     */
    private int positiveStickFillColor = DEFAULT_POSITIVE_STICK_FILL_COLOR;

    /**
     * <p>
     * Price down stick's border color
     * </p>
     * <p>
     * 値下りローソクのボーダー色
     * </p>
     * <p>
     * 阴线的边框颜色
     * </p>
     */

    private int negativeStickBorderColor = DEFAULT_NEGATIVE_STICK_BORDER_COLOR;

    /**
     * <p>
     * Price down stick's fill color
     * </p>
     * <p>
     * 値下りローソクの色
     * </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 sticks
     * </p>
     * <p>
     * スティックを書く用データ
     * </p>
     * <p>
     * 绘制柱条用的数据
     * </p>
     */
    private List<OHLCEntity> OHLCData;
    private List<OHLCEntity> newOHLCData;

    /**
     * <p>
     * max number of sticks
     * </p>
     * <p>
     * スティックの最大表示数
     * </p>
     * <p>
     * 柱条的最大表示数
     * </p>
     */
    private int maxSticksNum;

    /**
     * <p>
     * max value of Y axis
     * </p>
     * <p>
     * Y軸の最大値
     * </p>
     * <p>
     * Y的最大表示值
     * </p>
     */
    private double maxValue = 0;

    /**
     * <p>
     * min value of Y axis
     * </p>
     * <p>
     * Y軸の最小値
     * </p>
     * <p>
     * Y的最小表示值
     * </p>
     */
    private double minValue = 0;

    private boolean isChangeOHLCData = false;

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

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

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

    //逻辑更新
    protected void onUpdate() {
        updateOHLCData();
        checkMember();
        initMaxAndMin();
        initAxisY();
        initAxisX();
    }

    /*
     * (non-Javadoc)
     *
     * <p>Called when is going to draw this chart<p> <p>チャートを書く前、メソッドを呼ぶ<p>
     * <p>绘制图表时调用<p>
     *
     * @param canvas
     *
     * @see android.view.View#onDraw(android.graphics.Canvas)
     */
    @Override
    protected void onDraw(Canvas canvas) {
        onUpdate();
        super.onDraw(canvas);
    }

    @Override
    protected void drawChart(Canvas canvas) {
        super.drawChart(canvas);
        drawCandleSticks(canvas);
    }

    protected void initMaxAndMin() {
        if (null != getOHLCData()) {

            int minIndex = getOHLCData().size() - maxSticksNum;
            if (this.getStartIndex() > minIndex && minIndex > 0) {
                this.setStartIndex(minIndex);
            }

            for (int i = this.getStartIndex(); i >= 0 && i < getOHLCData().size()
                    && i < this.getStartIndex() + maxSticksNum; i++) {
                OHLCEntity ohlc = getOHLCData().get(i);

                if (i == this.getStartIndex()) {
                    maxValue = ohlc.getHigh();
                    minValue = ohlc.getLow();
                } else {
                    if (ohlc.getHigh() > maxValue) {
                        maxValue = ohlc.getHigh();
                    }
                    if (ohlc.getLow() < minValue) {
                        minValue = ohlc.getLow();
                    }
                }
            }
            double rate = 0.07;
            maxValue = (maxValue - minValue) * rate + maxValue;
            minValue = minValue - (maxValue - minValue) * rate;
            minValue = minValue < 0 ? 0 : minValue;
        }
    }

    @Override
    public int getAxisXPos(Object value) {
        float graduate = Float.valueOf(super.getAxisXGraduate(value));
        int pos = (int) Math.floor(graduate * maxSticksNum);

        if (pos >= maxSticksNum) {
            pos = maxSticksNum - 1;
        } else if (pos < 0) {
            pos = 0;
        }
        pos += this.getStartIndex();

        return pos;
    }

    /*
     * (non-Javadoc)
     *
     * @param value
     *
     */
    @Override
    protected String getAxisXValue(Object value) {
        int index = getAxisXPos(value);

        String ret = "";
        try {
            if (index < getOHLCData().size()) {
                ret = getOHLCData().get(index).getTime();
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return ret;
    }

    /**
     * <p>
     * get current selected data index
     * </p>
     * <p>
     * 選択したスティックのインデックス
     * </p>
     * <p>
     * 获取当前选中的柱条的index
     * </p>
     *
     * @return int
     * <p>
     * index
     * </p>
     * <p>
     * インデックス
     * </p>
     * <p>
     * index
     * </p>
     */
    public int getSelectedIndex() {
        if (null == super.getTouchPoint()) {
            return 0;
        }
        float graduate = Float.valueOf(super.getAxisXGraduate(super
                .getTouchPoint().x));
        int index = (int) Math.floor(graduate * maxSticksNum);

        if (index >= maxSticksNum) {
            index = maxSticksNum - 1;
        } else if (index < 0) {
            index = 0;
        }

        return index;
    }

    /*
     * (non-Javadoc)
     *
     * @param value
     *
     */
    @Override
    public String getAxisYGraduate(Object value) {
        float graduate = Float.valueOf(super.getAxisYGraduate(value));
        double dYVal = graduate * (maxValue - minValue) + minValue;
        String strYVal = getNumberFormat().format(dYVal);
        return strYVal;
    }

    /**
     * <p>
     * initialize degrees on Y axis
     * </p>
     * <p>
     * Y軸の目盛を初期化
     * </p>
     * <p>
     * 初始化Y轴的坐标值
     * </p>
     */
    protected void initAxisX() {
        List<String> TitleX = new ArrayList<String>();
        if (null != getOHLCData() && getOHLCData().size() > 0 && this.getStartIndex() >= 0) {
            float average = maxSticksNum / this.getLongitudeNum();
            for (int i = 0; i < this.getLongitudeNum(); i++) {
                int index = (int) Math.floor(i * average);
                if (index > maxSticksNum - 1) {
                    index = maxSticksNum - 1;
                }
                if (this.getStartIndex() + index < getOHLCData().size())
                    TitleX.add(getOHLCData().get(this.getStartIndex() + index).getTime());
            }
            if (this.getStartIndex() + maxSticksNum - 1 < getOHLCData().size())
                TitleX.add(getOHLCData().get(this.getStartIndex() + maxSticksNum - 1).getTime());
        }
        super.setAxisXTitles(TitleX);
    }

    public void setDecimalNum(int decimal) {
        super.setDecimalNum(decimal);
    }

    /**
     * <p>
     * initialize degrees on Y axis
     * </p>
     * <p>
     * Y軸の目盛を初期化
     * </p>
     * <p>
     * 初始化Y轴的坐标值
     * </p>
     */
    protected void initAxisY() {
        List<String> TitleY = new ArrayList<String>();
        if (maxValue == minValue){//这一步处理是有时会出现maxvalue和minvalue相同，导致y轴出现问题
            maxValue = maxValue + 0.1;
            minValue = minValue - 0.01;
        }
        double average = (maxValue - minValue) * 10000 / this.getLatitudeNum() / 10000;

        // calculate degrees on Y axis
        for (int i = 0; i < this.getLatitudeNum(); i++) {
            String value = getNumberFormat().format(minValue + i * average);
            if (value.length() < super.getAxisYMaxTitleLength()) {
                while (value.length() < super.getAxisYMaxTitleLength()) {
                    value = new String(" ") + value;
                }
            }
            TitleY.add(value);
        }
        // calculate last degrees by use max value
        String value = getNumberFormat().format(maxValue);
        if (value.length() < super.getAxisYMaxTitleLength()) {
            while (value.length() < super.getAxisYMaxTitleLength()) {
                value = new String(" ") + value;
            }
        }
        TitleY.add(value);

        super.setAxisYTitles(TitleY);
        if (super.isDisplayAxisYTitle() && super.getAxisYTitles() != null) {
            int counts = super.getAxisYTitles().size();
            Paint mPaintFont = new Paint();
            mPaintFont.setTextSize(super.getLatitudeFontSize());
            float textWidth = 0;
            float maxAxisMarginLeft = 0;
            for (int i = 0; i < counts; i++) {
                textWidth = mPaintFont.measureText(super.getAxisYTitles().get(i)) + 10;
                if (textWidth > maxAxisMarginLeft) {
                    maxAxisMarginLeft = textWidth;
                }
            }

            if (maxAxisMarginLeft > super.getNotifyAxisMarginLeft()) {
                super.setAxisMarginLeft(maxAxisMarginLeft);
                notifyEventAll(ITouchEventNotify.EVENT_MOVE, this);
            }
        }
    }

    /**
     * <p>
     * draw sticks
     * </p>
     * <p>
     * スティックを書く
     * </p>
     * <p>
     * 绘制柱条
     * </p>
     *
     * @param canvas
     */
    protected void drawCandleSticks(Canvas canvas) {
        float stickWidth = getItemWidth();
        float stickShowWidth = getItemShowWidth();
        float stickShowOffset = (stickWidth - stickShowWidth) / 2;
        float stickX = /*super.getAxisMarginLeft() + super.getAxisMarginRight()*/2f;//左右对称缩进，故值相同

        Paint mPaintPositive = new Paint();
//		mPaintPositive.setColor(positiveStickFillColor);
        mPaintPositive.setColor(positiveStickBorderColor);
        mPaintPositive.setStrokeWidth(2.0f);
        //mPaintPositive.setStyle(Paint.Style.STROKE);//FIXME : 去掉这行，蜡烛图的红色柱状显示为实心的

        Paint mPaintNegative = new Paint();
        mPaintNegative.setColor(negativeStickFillColor);
        mPaintNegative.setStrokeWidth(2.0f);

        Paint mPaintCross = new Paint();
        // FIXME 需要跟主题颜色匹配着变化

        mPaintCross.setColor(crossStarColor);
        mPaintCross.setStrokeWidth(2.0f);

        if (null != getOHLCData()) {

            int minIndex = getOHLCData().size() - maxSticksNum;
            if (this.getStartIndex() > minIndex && minIndex > 0) {
                this.setStartIndex(minIndex);
            }

            for (int i = this.getStartIndex(); i >= 0 && i < getOHLCData().size() && i < this.getStartIndex() + maxSticksNum; i++) {
                OHLCEntity ohlc = getOHLCData().get(i);
                float openY = (float) ((1f - (ohlc.getOpen() - minValue) * 10000000
                        / ((maxValue - minValue) * 10000) / 1000)
                        * (super.getHeight() - super.getAxisMarginBottom() - 2 * super.getAxisMarginTop()) + super
                        .getAxisMarginTop());
                float highY = (float) ((1f - (ohlc.getHigh() - minValue) * 10000000
                        / ((maxValue - minValue) * 10000) / 1000)
                        * (super.getHeight() - super.getAxisMarginBottom() - 2 * super.getAxisMarginTop()) + super
                        .getAxisMarginTop());
                float lowY = (float) ((1f - (ohlc.getLow() - minValue) * 10000000
                        / ((maxValue - minValue) * 10000) / 1000)
                        * (super.getHeight() - super.getAxisMarginBottom() - 2 * super.getAxisMarginTop()) + super
                        .getAxisMarginTop());
                float closeY = (float) ((1f - (ohlc.getClose() - minValue) * 10000000
                        / ((maxValue - minValue) * 10000) / 1000)
                        * (super.getHeight() - super.getAxisMarginBottom() - 2 * super.getAxisMarginTop()) + super
                        .getAxisMarginTop());

                float left = stickX + stickShowOffset - 0.5f;
                if (ohlc.getOpen() < ohlc.getClose()) {
                    // stick or line

                    /**
                     *  标记最新一口价格时显示的横线
                     */
//					if (i == getOHLCData().size() - 1) {
//						canvas.drawLine(1, openY, getWidth() - getAxisMarginRight() - getAxisMarginLeft(), openY, mPaintPositive);
//					}
                    if (stickShowWidth >= 2f) {
                        canvas.drawRect(left, closeY, left + stickShowWidth,
                                openY, mPaintPositive);
                    }
//					canvas.drawLine(stickX + stickWidth / 2f, highY, stickX
//							+ stickWidth / 2f, lowY, mPaintPositive);
                    canvas.drawLine(left + stickShowWidth / 2f, highY, left
                            + stickShowWidth / 2f, closeY, mPaintPositive);
                    canvas.drawLine(left + stickShowWidth / 2f, openY, left
                            + stickShowWidth / 2f, lowY, mPaintPositive);
//					canvas.drawRect(left, highY, left
//							+ stickShowWidth / 2f, closeY, mPaintPositive);
                } else if (ohlc.getOpen() > ohlc.getClose()) {
                    /**
                     *  标记最新一口价格时显示的横线
                     */
//					if (i == getOHLCData().size() - 1) {给对方的撒规划
//						canvas.drawLine(1, closeY, getWidth() - getAxisMarginRight() - getAxisMarginLeft(), closeY, mPaintPositive);
//					}
                    // stick or line
                    if (stickShowWidth >= 2f) {
                        canvas.drawRect(left, openY, left + stickShowWidth,
                                closeY, mPaintNegative);
                    }
                    canvas.drawLine(left + stickShowWidth / 2f, highY, left
                            + stickShowWidth / 2f, lowY, mPaintNegative);

                } else {
                    /**
                     *  标记最新一口价格时显示的横线
                     */
//					if (i == getOHLCData().size() - 1) {
//						canvas.drawLine(1, highY, getWidth() - getAxisMarginRight() - getAxisMarginLeft(), highY, mPaintPositive);
//					}
                    // line or point
                    if (stickShowWidth >= 2f) {
                        canvas.drawLine(left, closeY, left + stickShowWidth,
                                openY, mPaintCross);
                    }
                    canvas.drawLine(left + stickShowWidth / 2f, highY, left
                            + stickShowWidth / 2f, lowY, mPaintCross);
                }
                // next x
                stickX = stickX + stickWidth;
            }
        }
    }

    /**
     * 监听滑动
     */
    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
                            float distanceY) {
        // TODO Auto-generated method stub

        if (moveChart(distanceX)) {
            this.setTouchDistanceX(distanceX);
            notifyEventAll(ITouchEventNotify.EVENT_MOVE, this);
            this.setTouchDistanceX(0);
        }
        return true;
    }

    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        // TODO Auto-generated method stub
        if (zoomChart(detector)) {
            this.invalidate();
            notifyEventAll(ITouchEventNotify.EVENT_SCALE, this);
        }
        return false;
    }

    public boolean zoomChart(ScaleGestureDetector detector) {
        boolean isZoom = false;
        float ps = detector.getPreviousSpan();
        float cs = detector.getCurrentSpan();
        if (ps > cs + 5) {
            isZoom = zoomOut();
        } else if (ps < cs - 5) {
            isZoom = zoomIn();
        }
        return isZoom;
    }

    @Override
    public void notifyEvent(int eventId, GridChart chart) {
        switch (eventId) {
            case ITouchEventNotify.EVENT_MOVE: {
                moveChart(chart.getTouchDistanceX());
                changeMarginLeft(chart.getAxisMarginLeft());
                setNotifyAxisMarginLeft(chart.getAxisMarginLeft());
            }
            break;
            case ITouchEventNotify.EVENT_SCALE:
                zoomChart(chart.getScaleGestureDetector());
                super.invalidate();
                break;
            default:
                break;
        }
        super.notifyEvent(eventId, chart);
    }

    private void changeMarginLeft(float marginLeft) {
        if (super.isDisplayAxisYTitle()) {
            int counts = super.getAxisYTitles().size();
            Paint mPaintFont = new Paint();
            mPaintFont.setTextSize(super.getLatitudeFontSize());
            float textWidth = 0;
            float maxAxisMarginLeft = 0;
            for (int i = 0; i < counts; i++) {
                textWidth = mPaintFont.measureText(super.getAxisYTitles().get(i)) + 10;
                if (textWidth > maxAxisMarginLeft) {
                    maxAxisMarginLeft = textWidth;
                }
            }

            if (maxAxisMarginLeft < marginLeft && marginLeft != super.getAxisMarginLeft()) {
                super.setAxisMarginLeft(marginLeft);
                super.invalidate();
            }
        }
    }

    private boolean moveChart(float distance) {
        float fMoveNum = distance / getItemWidth();
        int nMoveNum = Math.round(fMoveNum);
        int tempIdx = 0;
        if (nMoveNum != 0) {
            tempIdx = this.getStartIndex() + nMoveNum;
            if (tempIdx <= getOHLCData().size() - this.getMaxSticksNum()) {
                this.setStartIndex(tempIdx);
                if (this.getStartIndex() < 0)
                    this.setStartIndex(0);
                super.invalidate();
                return true;
            }

        }
        return false;
    }

    @Override
    protected float getClickPosXOffset() {
        return getItemWidth() / 2;
    }

    @Override
    protected float getItemWidth() {
        return ((super.getWidth() - super.getAxisMarginLeft() - 2 * super.getAxisMarginRight()) / maxSticksNum);
    }

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


    /**
     * <p>
     * add a new stick data to sticks and refresh this chart
     * </p>
     * <p>
     * 新しいスティックデータを追加する，フラフをレフレシューする
     * </p>
     * <p>
     * 追加一条新数据并刷新当前图表
     * </p>
     *
     * @param entity <p>
     *               data
     *               </p>
     *               <p>
     *               データ
     *               </p>
     *               <p>
     *               新数据
     *               </p>
     */
    public void pushData(OHLCEntity entity) {
        if (null != entity) {
            // 追�?��据到数据列表
            addData(entity);
            // 强制重�?
            super.postInvalidate();
        }
    }

    /**
     * <p>
     * add a new stick data to sticks
     * </p>
     * <p>
     * 新しいスティックデータを追加する
     * </p>
     * <p>
     * 追加一条新数据
     * </p>
     *
     * @param entity <p>
     *               data
     *               </p>
     *               <p>
     *               データ
     *               </p>
     *               <p>
     *               新数据
     *               </p>
     */
    public void addData(OHLCEntity entity) {
        if (null != entity) {
            if (null == getOHLCData() || 0 == getOHLCData().size()) {
                setOHLCData(new ArrayList<OHLCEntity>());
//				this.minValue = ((int) entity.getLow()) / 10 * 10;
//				this.maxValue = ((int) entity.getHigh()) / 10 * 10;
            }

            this.getOHLCData().add(entity);

			/*if (this.minValue > entity.getLow()) {
                this.minValue = ((int) entity.getLow()) / 10 * 10;
			}

			if (this.maxValue < entity.getHigh()) {
				this.maxValue = 10 + ((int) entity.getHigh()) / 10 * 10;
			}

			if (OHLCData.size() > maxSticksNum) {
				maxSticksNum = maxSticksNum + 1;
			}*/
        }
    }

    private final int NONE = 0;
    private final int ZOOM = 1;
    private final int DOWN = 2;

    private float olddistance = 0f;
    private float newdistance = 0f;

    private int TOUCH_MODE;

	/*
	 * (non-Javadoc)
	 * 
	 * <p>Called when chart is touched<p> <p>チャートをタッチしたら、メソッドを呼ぶ<p>
	 * <p>图表点击时调用<p>
	 * 
	 * @param event
	 * 
	 * @see android.view.View#onTouchEvent(MotionEvent)
	 */
	/*@Override
	public boolean onTouchEvent(MotionEvent event) {

		final float MIN_LENGTH = (super.getWidth() / 40) < 5 ? 5 : (super
				.getWidth() / 50);

		switch (event.getAction() & MotionEvent.ACTION_MASK) {
		case MotionEvent.ACTION_DOWN:
			TOUCH_MODE = DOWN;
			break;
		case MotionEvent.ACTION_UP:
		case MotionEvent.ACTION_POINTER_UP:
			TOUCH_MODE = NONE;
			return super.onTouchEvent(event);
		case MotionEvent.ACTION_POINTER_DOWN:
			olddistance = calcDistance(event);
			if (olddistance > MIN_LENGTH) {
				TOUCH_MODE = ZOOM;
			}
			break;
		case MotionEvent.ACTION_MOVE:
			if (TOUCH_MODE == ZOOM) {
				newdistance = calcDistance(event);
				if (newdistance > MIN_LENGTH
						&& Math.abs(newdistance - olddistance) > MIN_LENGTH) {

					if (newdistance > olddistance) {
						zoomIn();
					} else {
						zoomOut();
					}
					olddistance = newdistance;

					super.postInvalidate();
					super.notifyEventAll(this);
				}
			}
			break;
		}
		return true;
	}*/

    /**
     * <p>
     * calculate the distance between two touch points
     * </p>
     * <p>
     * 複数タッチしたポイントの距離
     * </p>
     * <p>
     * 计算两点触控时两点之间的距离
     * </p>
     *
     * @param event
     * @return float
     * <p>
     * distance
     * </p>
     * <p>
     * 距離
     * </p>
     * <p>
     * 距离
     * </p>
     */
    private float calcDistance(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return (float) Math.sqrt(x * x + y * y);
    }

    /**
     * <p>
     * Zoom in the graph
     * </p>
     * <p>
     * 拡大表示する。
     * </p>
     * <p>
     * 放大表示
     * </p>
     */
    protected boolean zoomIn() {
        if (maxSticksNum > 10) {
            maxSticksNum = maxSticksNum - 3;
            return true;
        }
        return false;
    }

    /**
     * <p>
     * Zoom out the grid
     * </p>
     * <p>
     * 縮小表示する。
     * </p>
     * <p>
     * 缩小
     * </p>
     */
    protected boolean zoomOut() {
        if (maxSticksNum < getOHLCData().size() - 3) {
            int temp = maxSticksNum;
            maxSticksNum = maxSticksNum + 3;
            if (this.getItemWidth() < 1) {
                maxSticksNum = temp;
                return false;
            }
            return true;
        }
        return false;
    }

    /**
     * @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;
    }

    /**
     * @return the crossStarColor
     */
    public int getCrossStarColor() {
        return crossStarColor;
    }

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

    private void updateOHLCData() {
        if (isChangeOHLCData) {
            isChangeOHLCData = false;
            if (newOHLCData != null) {

                if (OHLCData == null) {
                    OHLCData = new ArrayList<OHLCEntity>();
                }
				/*for (OHLCEntity e : newOHLCData) {
					addData(e);
				}*/
                OHLCData.clear();
                OHLCData.addAll(newOHLCData);

            }
        }
    }

    /**
     * @return the oHLCData
     */
    public List<OHLCEntity> getOHLCData() {
        if (OHLCData == null) {
            OHLCData = new ArrayList<OHLCEntity>();
        }
        return OHLCData;
    }

    /**
     * @param oHLCData the oHLCData to set
     */
    public void setOHLCData(List<OHLCEntity> oHLCData) {
        if (newOHLCData == null) {
            newOHLCData = new ArrayList<OHLCEntity>();
        }
        newOHLCData.clear();
        newOHLCData.addAll(oHLCData);
        isChangeOHLCData = true;
    }

    /**
     * @return the maxSticksNum
     */
    public int getMaxSticksNum() {
        return maxSticksNum;
    }

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

    /**
     * @return the maxValue
     */
    public double getMaxValue() {
        return maxValue;
    }

    /**
     * @param maxValue the maxValue to set
     */
    public void setMaxValue(double maxValue) {
        this.maxValue = maxValue;
    }

    /**
     * @return the minValue
     */
    public double getMinValue() {
        return minValue;
    }

    /**
     * @param minValue the minValue to set
     */
    public void setMinValue(double minValue) {
        this.minValue = minValue;
    }

    private void checkMember() {
        if (this.getStartIndex() < 0) {
            int minIndex = getOHLCData().size() - maxSticksNum;
            if (minIndex > 0) {
                setStartIndex(minIndex);
            } else if (getOHLCData().size() > 0) {
                setStartIndex(0);
                //setMaxSticksNum(getOHLCData().size());
            }
        }
    }
}
