package cn.muchinfo.rma.view.base.chart.old.controls;

import android.app.Activity;
import android.content.res.Configuration;
import android.text.Html;
import android.view.View;
import android.widget.TextView;


import com.desfate.chart.ChartConstant;
import com.desfate.chart.ChartEnums;
import com.desfate.chart.Configs;
import com.desfate.chart.R;
import com.desfate.chart.data.ChartData;
import com.desfate.chart.data.ChartDataContainer;
import com.desfate.chart.entity.OHLCEntity;
import com.desfate.chart.entity.StickEntity;
import com.desfate.chart.ui.old.OTC.datas.HistoryCycle;
import com.desfate.chart.ui.old.OTC.datas.SettlementPlan;
import com.desfate.chart.ui.old.OnQuoteAddListener;
import com.desfate.chart.util.LogUtils;
import com.desfate.chart.util.MathUtil;

import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import cn.muchinfo.rma.global.data.GoodsInfoAndQuotes;
import cn.muchinfo.rma.view.base.chart.ChartDataAdapter;


/**
 * 图表的数据处理、控制类
 *
 * @author Administrator
 */
public class MTPChartControl {
    private Activity activity;
    /**
     * 分时图1分钟数据
     */
    public final static String TIME_M1 = "TIME_M1";
    /**
     * 分时图5分钟数据
     */
    // public final static String TIME_M5 = "TIME_M5";
    /**
     * K线1分钟
     */
    public final static String K_M1 = "K_M1";
    /**
     * k线5分钟
     */
    public final static String K_M5 = "K_M5";
    /**
     * k线15分钟
     */
    public final static String K_M15 = "K_M15";
    /**
     * k线30分钟
     */
    public final static String K_M30 = "K_M30";
    /**
     * k线60分钟
     */
    public final static String K_M60 = "K_M60";
    /**
     * k线2xiaoshi
     */
    public final static String K_M120 = "K_M120";
    /**
     * k线240分钟
     */
    public final static String K_M240 = "K_M240";

    /**
     * 日线
     */
    public final static String K_DAY = "K_DAY";
    /**
     * 周线
     */
    public final static String K_WEEK = "K_WEEK";
    /**
     * 月线
     */
    public final static String K_MONTH = "K_MONTH";
    /**
     * 月线
     */
    public final static String K_YEAR = "K_YEAR";
    /**
     * 月线
     */
    public final static String K_QUARTER = "K_QUARTER";

    // 当前标签，是分时图还是k线等数据
    private int currentTab;

    // 横屏或竖屏标志
    private int orientation = 1;

    // 小数位
    private int decimalPlace;
    private HashMap<String, ChartDataContainer> dataMap = new HashMap<String, ChartDataContainer>();
    DateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.CHINA);
    private List<String> timeList = new ArrayList<String>();
    private List<Double> timePriceList = new ArrayList<Double>();
    private List<Double> avgList = new ArrayList<Double>();
    private int goodsId;
    private GoodsInfoAndQuotes goodsInfo;
    private SettlementPlan settlementPlan;
    private int realCount = 0;// 实际的分时图数据条数
    private int showIndex = 0;// 显示的分时图最新index
    //private int reduce = 60000;// 分时图时间间隔
    private int reduce = 300000;// FIXME :分时图时间间隔
    private double max = 0;
    private double min = 0;
    private long kReduce = 60000; // k线间隔
    private int startIndex = -1;
    private int preSize = 0;
    private ScheduledExecutorService _sExecutorService;
    private OnQuoteAddListener listener;
    private ArrayList<Integer> virtualIndexList = new ArrayList<Integer>();

    public void setStartIndex(int startIndex) {
        this.startIndex = startIndex;
    }

    public void setPreSize(int preSize) {
        this.preSize = preSize;
    }

    public int getStartIndex() {
        return startIndex;
    }

    public void indexIncrease() {
        startIndex++;
    }

    public double getMax() {
        return max;
    }

    public void setMax(double max) {
        this.max = max;
    }

    public double getMin() {
        return min;
    }

    public void setMin(double min) {
        this.min = min;
    }

    public void setActivity(Activity activity) {
        this.activity = activity;
    }

    public Calendar getOldestTime(int goodsID, int type) {
//        List<HistoryCycle> list = MarketDataTools.getHistoryCycle(goodsID, type);
//        if (list == null || list.isEmpty()) {
//            return null;
//        }
//        Date time = list.get(list.size() - 1).getStartTime();
//        Calendar calendar = Calendar.getInstance();
//        calendar.setTime(time);
//        return calendar;
        return null;
    }

    public Calendar getKLastTime(int goodsID, int type) {
//        List<HistoryCycle> list = MarketDataTools.getHistoryCycle(goodsID, type);
//        if (list == null || list.isEmpty()) {
//            return null;
//        }
//        Date time = list.get(0).getStartTime();
//        Calendar calendar = Calendar.getInstance();
//        calendar.setTime(time);
//        return calendar;
        return null;
    }

    /**
     * 获取之前的size
     *
     * @return
     */
    private int getPreSize() {
        return preSize;
    }

    /**
     * 是否可买平
     *
     * @param goodsId
     * @return
     */
    public Boolean getCanBuyCloseOrNot(int goodsId) {
//        ArrayList<TradeSummaryData> list = GlobalDataCollention.getInstance().getTradePositionData();
//        if (list == null) {
//            return false;
//        }
//        for (int i = 0; i < list.size(); i++) {
//            TradeSummaryData item = list.get(i);
//            if (item.getGoodsid() == goodsId) {
//                if ((MTPEnums.DIRECTION_SALE + "").equals(item.getBuyorsell()) && Double.parseDouble(item.getPositionqty()) > 0) {
//                    return true;
//                }
//            }
//        }
        return false;
    }

    /**
     * 是否可卖平
     *
     * @param goodsId
     * @return
     */
    public boolean getCanSellCloseOrNot(int goodsId) {
//        ArrayList<TradeSummaryData> list = GlobalDataCollention.getInstance().getTradePositionData();
//        if (list == null) {
//            return false;
//        }
//        for (int i = 0; i < list.size(); i++) {
//            TradeSummaryData item = list.get(i);
//            if (item.getGoodsid() == goodsId) {
//                if ((MTPEnums.DIRECTION_BUY + "").equals(item.getBuyorsell()) && Double.parseDouble(item.getPositionqty()) > 0) {
//                    return true;
//                }
//            }
//        }

        return false;
    }

    public int getShowIndex() {
        return showIndex;
    }

    public void setShowIndex(int showIndex) {
        this.showIndex = showIndex;
    }

    public SettlementPlan getSettlementPlan() {
        return settlementPlan;
    }

    public void setSettlementPlan(SettlementPlan settlementPlan) {
        this.settlementPlan = settlementPlan;
    }

    public MTPChartControl(Activity activity) {
        dataMap.put(TIME_M1, new ChartDataContainer());
        dataMap.put(K_M15, new ChartDataContainer());
        dataMap.put(K_M1, new ChartDataContainer());
        dataMap.put(K_M5, new ChartDataContainer());
        dataMap.put(K_M30, new ChartDataContainer());
        dataMap.put(K_M60, new ChartDataContainer());
        dataMap.put(K_M120, new ChartDataContainer());
        dataMap.put(K_M240, new ChartDataContainer());
        dataMap.put(K_DAY, new ChartDataContainer());
        dataMap.put(K_WEEK, new ChartDataContainer());
        dataMap.put(K_MONTH, new ChartDataContainer());
        dataMap.put(K_YEAR, new ChartDataContainer());
        dataMap.put(K_QUARTER, new ChartDataContainer());
        this.activity = activity;
        _sExecutorService = Executors.newSingleThreadScheduledExecutor();
    }

    /**
     * 启动定时器,用来监测是否要补行情
     */
    public void startExecutorService(OnQuoteAddListener listener) {
//        if (!OTCChartActivity.drwaTimeChart) {
//            return;
//        }
        this.listener = listener;
        long current = System.currentTimeMillis();
        long preDelay = current - (current % reduce) + reduce - current;
        long afterDelay = reduce;
        LogUtils.e("chart", "predelay" + preDelay);
        // _sExecutorService.scheduleWithFixedDelay(new AutoDrawJob(), preDelay,
        // afterDelay, TimeUnit.MILLISECONDS);
        // try {
        _sExecutorService.scheduleAtFixedRate(new AutoDrawJob(), preDelay, afterDelay, TimeUnit.MILLISECONDS);
        // } catch (Exception e) {
        // LogUtils.e("chart", "我操 崩溃了");
        // // TODO Auto-generated catch block
        // e.printStackTrace();
        // }
        beforeLoop();
    }

    /**
     * 如果没有分时数据怎么搞
     */
    public void timeDataNullHandle(Date startTime, Date endTime) {
        // String startString = df2.format(startTime);
        // int startIndex = findIndexOfTime(startString);
        // if (timePriceList == null || timePriceList.size() <= 0) {
        timeDataInit();
        // }
        // else {
        // ChartDataContainer container = get();
        // double price = timePriceList.get(startIndex -1);
        // for (int i = startIndex; i < endIndex; i++) {
        // ((ChartData)container.mOHLCList.get(i)).setDataType(ChartData.NoneDraw);
        // }
        // }
    }

    public void disposed() {
        try {
            LogUtils.e("chart", "disposed了");
            _sExecutorService.shutdown();
            _sExecutorService = Executors.newSingleThreadScheduledExecutor();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * 请求分时数据超时处理
     */
    public void timeDataTimeoutHandle() {
        timeDataInit();
    }

    // /**
    // * 如果数据正常怎么搞
    // */
    // public void timeDataSuccessHandle(Date startTime, Date endTime){
    // // 得到了分钟线数据
    // List<HistoryCycle> cycles = QuoteManager.getInstance().
    // getHistoryCycle(goodsId, MTPEnums.HistoryData_Minute, startTime, endTime,
    // 0);
    // if(cycles == null || cycles.size() <= 0){
    // // 正常情况数据不应该为空，待考虑如果数据为空如何做
    // timeDataNullHandle(startTime, endTime);
    // return;
    // }
    // ChartDataContainer container = get();
    // startTime.setTime(startTime.getTime() - (long)(startTime.getTime() %
    // 60000));
    // HashMap<String, HistoryCycle> map = toMap(cycles);
    // int startIndex = findIndexOfTime(df2.format(startTime));
    // int endIndex = findIndexOfTime(df2.format(endTime));
    // for (int i = startIndex; i < timeList.size(); i++) {
    // HistoryCycle item = map.get(timeList.get(i));
    // int dataType = -1;
    // if(item == null){
    // // 如果在请求的数据集中有该时间点数据
    // item = new HistoryCycle();
    // if(i == 0){
    // // 如果数据集中不存在该时间点数据，而且是开盘第一条，取昨收作为
    // // 收盘价
    // double preClosed = getPreClosed();
    // item.setOpened(preClosed);
    // item.setHighest(preClosed);
    // item.setLowest(preClosed);
    // item.setClosed(preClosed);
    // avgList.add(getPreClosed());
    // }else {
    // // 如果不是第一个，价格设置为前一时间点一致
    // double prePrice = timePriceList.get(i - 1);
    // item.setOpened(prePrice);
    // item.setHighest(prePrice);
    // item.setLowest(prePrice);
    // item.setClosed(prePrice);
    // avgList.add(avgList.get(i - 1));
    // }
    // if(!virtualIndexList.contains(i)){
    // virtualIndexList.add(i);
    // }
    // }else {
    // dataType = ChartData.Perfect;
    // if(i == 0){
    // avgList.add(item.getClosed());
    // realCount++;
    // }else {
    // avgList.add((realCount * avgList.get(i - 1) + item.getClosed()) /
    // (realCount + 1));
    // realCount++;
    // }
    // if(virtualIndexList.contains(i)){
    // virtualIndexList.remove(i);
    // }
    // }
    // timePriceList.add(item.getClosed());
    // ChartData chartData = null;
    // // 重用对象，如果当前item在源数据集中能找到对象，直接用
    // if (i < container.mOHLCList.size()) {
    // chartData = (ChartData) container.mOHLCList.get(i);
    // }
    //
    // // 否则使用新的
    // if(chartData == null){
    // container.mOHLCList.add(new ChartData(item.getOpened(),
    // item.getHighest(), item.getLowest(), item.getClosed(), timeList.get(i)));
    // }else {
    // // 这是存在对象的情况
    // chartData.setOpen(item.getOpened());
    // chartData.setHigh(item.getHighest());
    // chartData.setLow(item.getLowest());
    // chartData.setClose(item.getClosed());
    // chartData.setTime(timeList.get(i));
    // if(dataType != -1){
    // chartData.setDataType(dataType);
    // if (dataType == ChartData.AutoDraw) {
    // if (!virtualIndexList.contains(i)) {
    // virtualIndexList.add(i);
    // }
    // } else {
    // if (virtualIndexList.contains(i)) {
    // virtualIndexList.remove(i);
    // }
    // }
    // }
    // }
    // }
    // max = getMaxValue();
    // min = getMinValue();
    // calcChartDataType(map, startIndex, endIndex, container);
    // }

    /**
     * 如果分时数据为空，初始化time，price,avg列表
     */
    private void timeDataInit() {
        // 循环得到了时间list
        Date sTime = settlementPlan.getOpenTime();
        long startTimeS = sTime.getTime();
        Date eTime = settlementPlan.getReckonTime();
        long endTimeS = eTime.getTime();
        timeList.clear();
        timePriceList.clear();
        avgList.clear();
        for (long time = startTimeS; time <= endTimeS; time += reduce) {
            Date dateTime = new Date(time);
            if (settlementPlan.inPlan(dateTime)) {
                timeList.add(df2.format(dateTime));
            }
        }

        double preClosed = 0;
        try {
            preClosed = goodsInfo.getQuoteDayData().getPresettle();
        } catch (Exception e) {
            // TODO: handle exception
        }

        if (preClosed == 0) {
//            OTCChartActivity.drwaTimeChart = false;
            // 没有昨收，不画分时图
            return;
        }

        ChartDataContainer container = get();
        container.mOHLCList.clear();
        ChartData chartData = new ChartData();
        chartData.setOpen(preClosed);
        chartData.setHigh(preClosed);
        chartData.setLow(preClosed);
        chartData.setClose(preClosed);
        chartData.setVolume("0");
        // 初始化
        for (int i = 0; i < timeList.size(); i++) {
            timePriceList.add(preClosed);
            avgList.add(preClosed);
            container.mOHLCList.add(chartData);
            container.mOHLCList.get(i).setTime(timeList.get(i));
        }
        min = getMinValue();
        max = getMaxValue();
    }

    /**
     * 1分钟分时图 数据为空，初始化time，price,avg列表
     */
    public void charttimeDataInit() {
        // 循环得到了时间list
        Date sTime = settlementPlan.getOpenTime();
        long startTimeS = sTime.getTime();
        Date eTime = settlementPlan.getReckonTime();
        long endTimeS = eTime.getTime();
        timeList.clear();
        timePriceList.clear();
        avgList.clear();
        for (long time = startTimeS; time <= endTimeS; time += 60000) {
            Date dateTime = new Date(time);
            if (settlementPlan.inPlan(dateTime)) {
                timeList.add(df2.format(dateTime));
            }
        }

        double preClosed = 0;
        try {
            preClosed = goodsInfo.getQuoteDayData().getPresettle();
        } catch (Exception e) {
            // TODO: handle exception
        }

        if (preClosed == 0) {
//            OTCChartActivity.drwaTimeChart = false;
            // 没有昨收，不画分时图
            return;
        }

        ChartDataContainer container = get();
        container.mOHLCList.clear();
        ChartData chartData = new ChartData();
        chartData.setOpen(preClosed);
        chartData.setHigh(preClosed);
        chartData.setLow(preClosed);
        chartData.setClose(preClosed);
        chartData.setVolume("0");
        // 初始化
        for (int i = 0; i < timeList.size(); i++) {
            timePriceList.add(preClosed);
            avgList.add(preClosed);
            container.mOHLCList.add(chartData);
            container.mOHLCList.get(i).setTime(timeList.get(i));
        }
        min = getMinValue();
        max = getMaxValue();
    }

    /**
     * 定时器第一次执行前要做的
     */
    private void beforeLoop() {
        long currentTime = System.currentTimeMillis();
        long cycleTimeMSeconds = currentTime - currentTime % reduce;
        // 得到当前所在周期时间的时间对象
        Date cycleTime = new Date(cycleTimeMSeconds);
        String timeString = df2.format(cycleTime);
        // 得到所在周期在的时间index
        int cycleIndex = findIndexOfTime(timeString);
        if (cycleIndex <= showIndex || cycleIndex < 0) {
            // 如果当前时间所在周期index，小于所显示的index，说明已经画了这个周期的，不用画了
            return;
        }

        if (showIndex <= 0) {
            // 说明没有数据
        }

        int sub = cycleIndex - showIndex;
        if (sub == 1) {
            /*
			 * 如果刚好等于1，这是理想情况，补一根线，
			 */
            // 将显示的index设置为当前周期index
            showIndex = cycleIndex;
            // 标记当前周期数据为假的
            ChartDataContainer container = get();
            double price = timePriceList.get(cycleIndex - 1);
            ChartData chartData = (ChartData) container.mOHLCList.get(showIndex);
            chartData.setOpen(price);
            chartData.setHigh(price);
            chartData.setLow(price);
            chartData.setClose(price);
            chartData.setVolume("0");
            chartData.setDataType(ChartData.AutoDraw);
            if (!virtualIndexList.contains(showIndex)) {
                virtualIndexList.add(showIndex);
            }
            // 这里就不要请求了，因为刚刚得到回应
            // if(virtualIndexList.size() > 0){
            // byVirtualList(showCount);
            // }
            // 调用绘制
            listener.reFreshChartAfterAdd(true, false);
        } else if (sub > 1) {
			/*
			 * 如果当前时间大于之前1个以上的周期 1先画一根当前周期的数据(该笔数据要标记为假数据)，
			 * 2.然后发送修补请求，请求该段时间的数据，尝试补回，逻辑和来了实时行情补数据一样。
			 */

            // 将该段数据设为假
            ChartDataContainer container = get();
            if (timePriceList != null && timePriceList.size() > 0) {
                double price = timePriceList.get(showIndex);
                for (int i = showIndex; i <= cycleIndex; i++) {
                    ChartData chartData = (ChartData) container.mOHLCList.get(i);
                    chartData.setDataType(ChartData.AutoDraw);
                    chartData.setOpen(price);
                    chartData.setHigh(price);
                    chartData.setLow(price);
                    chartData.setClose(price);
                    chartData.setVolume("0");
                    if (!virtualIndexList.contains(i)) {
                        virtualIndexList.add(i);
                    }
                }
                showIndex = cycleIndex;
                container.mSize = showIndex + 1;
                listener.reFreshChartAfterAdd(true, false);
            }
            // 刚请求完，暂时没必要去做这个动作
            // byVirtualList(showCount);
            // 根据假数据列表，请求历史数据
        }
    }

    /**
     * 修补行情线程
     *
     * @author yongzq
     */
    private class AutoDrawJob implements Runnable {
        @Override
        public void run() {
            try {
                // 如果已经关闭
                if (!settlementPlan.inPlan(new Date(System.currentTimeMillis()))) {
                    return;
                }
//                if (!OTCChartActivity.drwaTimeChart) {
//                    return;
//                }
                if (_sExecutorService.isShutdown()) {
                    return;
                }
                long currentTime = System.currentTimeMillis();
                long cycleTimeMSeconds = currentTime - currentTime % reduce;
                // 得到当前所在周期时间的时间对象
                Date cycleTime = new Date(cycleTimeMSeconds);
                String timeString = df2.format(cycleTime);
                // 得到所在周期在的时间index
                int cycleIndex = findIndexOfTime(timeString);
                if (cycleIndex <= showIndex) {
                    // 如果当前时间所在周期index，小于所显示的index，说明已经画了这个周期的，不用画了
                    return;
                }

                int sub = cycleIndex - showIndex;
                if (sub == 1) {
					/*
					 * 如果刚好等于1，这是理想情况，补一根线， 然后尝试找之前是否有假的数据，如果有，并且上一次请求间隔大于某个时间
					 */
                    if (virtualIndexList.size() > 0) {
                        byVirtualList(showIndex);
                    }
                    // 将显示的index设置为当前周期index
                    showIndex = cycleIndex;

                    // 标记当前周期数据为假的
                    ChartDataContainer container = get();
                    container.mSize++;
                    double price = timePriceList.get(showIndex - 1);
                    ChartData chartData = (ChartData) container.mOHLCList.get(showIndex);
                    chartData.setOpen(price);
                    chartData.setHigh(price);
                    chartData.setLow(price);
                    chartData.setClose(price);
                    chartData.setDataType(ChartData.AutoDraw);
                    chartData.setTime(timeList.get(showIndex));
                    timePriceList.set(showIndex, price);
                    calcAvg(showIndex, price);
                    if (!virtualIndexList.contains(showIndex)) {
                        virtualIndexList.add(showIndex);
                    }
                    // 调用绘制
                    listener.reFreshChartAfterAdd(true, false);
                } else if (sub > 1) {
					/*
					 * 如果当前时间大于之前1个以上的周期 1先画一根当前周期的数据(该笔数据要标记为假数据)，
					 * 2.然后发送修补请求，请求该段时间的数据，尝试补回，逻辑和来了实时行情补数据一样。
					 */

                    // 将该段数据设为假
                    ChartDataContainer container = get();
                    double price = timePriceList.get(showIndex);
                    for (int i = showIndex; i <= cycleIndex; i++) {
                        ChartData chartData = (ChartData) container.mOHLCList.get(i);
                        chartData.setOpen(price);
                        chartData.setHigh(price);
                        chartData.setLow(price);
                        chartData.setClose(price);
                        chartData.setDataType(ChartData.AutoDraw);
                        chartData.setVolume("0");
                        if (!virtualIndexList.contains(i)) {
                            virtualIndexList.add(i);
                        }
                    }

                    showIndex = cycleIndex;
                    listener.reFreshChartAfterAdd(true, false);

                    // 根据假数据列表，请求历史数据
                    byVirtualList(showIndex);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void byVirtualList(int lastIndex) {
        int min = Integer.MAX_VALUE;
        if (virtualIndexList.size() > 0) {
            for (int i = 0; i < virtualIndexList.size(); i++) {
                if (virtualIndexList.get(i) < lastIndex) {
                    min = virtualIndexList.get(i);
                }
            }

            String lastTimeString = "";
            if (min < timeList.size()) {
                lastTimeString = timeList.get(min);
            } else {
                return;
            }

            try {
                Date endTime = df2.parse(timeList.get(lastIndex));
                Date lastTime = df2.parse(lastTimeString);
                // 一分钟内顶多请求一次
                listener.requestTimeData(lastTime, endTime, goodsId);
            } catch (Exception ex) {

            }
        }
    }

    public int getM5Color() {
        if(Configs.Chart_Color){
            return activity.getResources().getColor(R.color.p_item_click);
        }
        return activity.getResources().getColor(R.color.mtp_chart_t_m5_m1);
    }

    public int getAVGColor() {
        return activity.getResources().getColor(R.color.mtp_chart_t_avg);
    }

    /**
     * source += "<font color='#333333'>MA5:%s </font>";
     *minuts.setLineColor(((OTCChartActivity) getActivity()).getMtpChartControl().getM5Color());
     * @return
     */
    public int getMA5Color() {
        if(Configs.Chart_Color){
            return activity.getResources().getColor(R.color.p_item_click);
        }
        return activity.getResources().getColor(R.color.mtp_chart_k_ma5);
    }

    /**
     * source += "<font color='#D6417D'>MA10:%s </font>";
     *
     * @return
     */
    public int getMA10Color() {
        return activity.getResources().getColor(R.color.mtp_chart_k_ma10);
    }

    /**
     * source += "<font color='#379A7B'>MA15:%s</font>";
     *
     * @return
     */
    public int getMA15Color() {
        return activity.getResources().getColor(R.color.mtp_chart_k_ma15);
    }

    public int getMACDDEAColor() {
        return activity.getResources().getColor(R.color.mtp_chart_k_macd_dea);
    }

    public int getMACDDIFColor() {
        if(Configs.Chart_Color){
            return activity.getResources().getColor(R.color.p_item_click);
        }
        return activity.getResources().getColor(R.color.mtp_chart_k_macd_dif);
    }

    /**
     * 每个主题的主要颜色
     *
     * @return
     */
    public int getNormalTextColor() {
        return activity.getResources().getColor(R.color.p_normal_summary_txt_color);
    }

    public int getRSI6Color() {
        return activity.getResources().getColor(R.color.mtp_chart_k_rsi6);
    }
    public int getRSI12Color() {
        return activity.getResources().getColor(R.color.mtp_chart_k_rsi12);
    }
    public int getRSI24Color() {
        return activity.getResources().getColor(R.color.mtp_chart_k_rsi24);
    }

    public int getPSYColor() {
        return activity.getResources().getColor(R.color.mtp_chart_k_psy);
    }

    public int getPSYMAColor() {
        if(Configs.Chart_Color){
            return activity.getResources().getColor(R.color.p_item_click);
        }
        return activity.getResources().getColor(R.color.mtp_chart_k_psy_ma);
    }

    public int getDMAColor() {
        return activity.getResources().getColor(R.color.mtp_chart_k_dma);
    }

    public int getDMAAMAColor() {
        if(Configs.Chart_Color){
            return activity.getResources().getColor(R.color.p_item_click);
        }
        return activity.getResources().getColor(R.color.mtp_chart_k_dma_ama);
    }

    public int getKDJKColor() {
        return activity.getResources().getColor(R.color.mtp_chart_k_kdj_k);
    }

    public int getKDJDColor() {
        return activity.getResources().getColor(R.color.mtp_chart_k_kdj_d);
    }

    public int getKDJJColor() {
        // FIXME: 2019-05-21 这些先这样写  回头要新加配置
        if(Configs.Chart_Color){
            return activity.getResources().getColor(R.color.p_item_click);
        }
        return activity.getResources().getColor(R.color.mtp_chart_k_kdj_j);
    }

    public int getBIAS6Color() {
        return activity.getResources().getColor(R.color.mtp_chart_k_bias_6);
    }

    public int getBIAS12Color() {
        return activity.getResources().getColor(R.color.mtp_chart_k_bias_12);
    }

    public int getBIAS24Color() {
        if(Configs.Chart_Color){
            return activity.getResources().getColor(R.color.p_item_click);
        }
        return activity.getResources().getColor(R.color.mtp_chart_k_bias_24);
    }

    public int getCCIColor() {
        return activity.getResources().getColor(R.color.mtp_chart_k_cci);
    }

    public int getVOL5Color() {
        return activity.getResources().getColor(R.color.mtp_chart_k_total5);
    }

    public int getVOL10Color() {
        return activity.getResources().getColor(R.color.mtp_chart_k_total10);
    }

    /**
     * 设置当前界面状态
     *
     * @param currentTab
     */
    public void setCurrentTab(int currentTab) {
        this.currentTab = currentTab;
        switch (currentTab) {
            case ChartConstant.K_1:
                kReduce = 60 * 1000;
                break;
            case ChartConstant.K_5:
                kReduce = 60 * 1000 * 5;
                break;
            case ChartConstant.K_30:
                kReduce = 60 * 1000 * 30;
                break;
            case ChartConstant.K_15:
                kReduce = 60 * 1000 * 15;
                break;
            case ChartConstant.K_60:
                kReduce = 60 * 1000 * 60;
                break;
            case ChartConstant.K_240:
                kReduce = 60 * 1000 * 240;
                break;
            case ChartConstant.K_DAY:
                kReduce = 60 * 1000 * 60 * 24;
                break;
            case ChartConstant.K_WEEK:
                kReduce = 60 * 1000 * 60 * 24 * 7;
                break;
            case ChartConstant.K_MONTH:
                kReduce = 60 * 1000 * 60 * 24 * 30L;
                break;
            case ChartConstant.K_YEAR:
                kReduce = 12 * 60 * 1000 * 60 * 24 * 30L;
                break;
            default:
                break;
        }
    }

    /**
     * 设置横竖屏状态
     *
     * @param orientation
     */
    public void setOrientation(int orientation) {
        this.orientation = orientation;
        avgList.clear();
    }

    /**
     * 获取当前数据集，根据当前的tab来取数据
     *
     * @return
     */
    public ChartDataContainer get() {
        String type = "";
        switch (currentTab) {
            case ChartConstant.TIME:
                // if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
                type = TIME_M1;
                // } else {
                // type = TIME_M5;
                // }
                break;
            case ChartConstant.K_1:
                type = K_M1;
                break;
            case ChartConstant.K_5:
                type = K_M5;
                break;
            case ChartConstant.K_15:
                type = K_M15;
                break;
            case ChartConstant.K_30:
                type = K_M30;
                break;
            case ChartConstant.K_60:
                type = K_M60;
                break;
            case ChartConstant.K_120:
                type = K_M120;
                break;
            case ChartConstant.K_240:
                type = K_M240;
                break;
            case ChartConstant.K_DAY:
                type = K_DAY;
                break;
            case ChartConstant.K_WEEK:
                type = K_WEEK;
                break;
            case ChartConstant.K_MONTH:
                type = K_MONTH;
                break;
            case ChartConstant.K_YEAR:
                type = K_YEAR;
                break;
            case ChartConstant.K_QUARTER:
                type = K_QUARTER;
                break;
            default:
                break;
        }
        return dataMap.get(type);
    }

    public void reMove(String key) {
        try {
            dataMap.put(key, new ChartDataContainer());
        } catch (Exception e) {
            // TODO: handle exception
        }
    }

    private String getType() {
        String type = "";
        switch (currentTab) {
            case ChartConstant.TIME:
                // if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
                type = TIME_M1;
                // } else {
                // type = TIME_M5;
                // }
                break;
            case ChartConstant.K_1:
                type = K_M1;
                break;
            case ChartConstant.K_5:
                type = K_M5;
                break;
            case ChartConstant.K_15:
                type = K_M15;
                break;
            case ChartConstant.K_30:
                type = K_M30;
                break;
            case ChartConstant.K_60:
                type = K_M60;
                break;
            case ChartConstant.K_240:
                type = K_M240;
                break;
            case ChartConstant.K_DAY:
                type = K_DAY;
                break;
            case ChartConstant.K_WEEK:
                type = K_WEEK;
                break;
            case ChartConstant.K_MONTH:
                type = K_MONTH;
                break;
            case ChartConstant.K_YEAR:
                type = K_YEAR;
                break;
            case ChartConstant.K_QUARTER:
                type = K_QUARTER;
                break;
            default:
                break;
        }
        return type;
    }

    public ChartDataContainer get(String type) {
        return dataMap.get(type);
    }

    /**
     * 设置goodsid
     *
     * @param goodsId
     */
    public void setGoodsId(int goodsId) {
        this.goodsId = goodsId;

        goodsInfo = new ChartDataAdapter().getGoodsData().getGoodsInfoAndQuotesList().get(this.goodsId);
        if(goodsInfo == null){
            return;
        }
        decimalPlace = goodsInfo.getGoodsInfo().getDecimalplace();
        clearDatas();
    }

    private void clearDatas() {
        try {
            dataMap.put(TIME_M1, new ChartDataContainer());
            // dataMap.put(TIME_M5, new ChartDataContainer());
            dataMap.put(K_M1, new ChartDataContainer());
            dataMap.put(K_M5, new ChartDataContainer());
            dataMap.put(K_M15,new ChartDataContainer());
            dataMap.put(K_M30, new ChartDataContainer());
            dataMap.put(K_M60, new ChartDataContainer());
            dataMap.put(K_M120, new ChartDataContainer());
            dataMap.put(K_M240, new ChartDataContainer());
            dataMap.put(K_DAY, new ChartDataContainer());
            dataMap.put(K_WEEK, new ChartDataContainer());
            dataMap.put(K_MONTH, new ChartDataContainer());
            dataMap.put(K_YEAR, new ChartDataContainer());
            dataMap.put(K_QUARTER, new ChartDataContainer());
            _sExecutorService = Executors.newSingleThreadScheduledExecutor();
            showIndex = 0;
            timeList = new ArrayList<String>();
            timePriceList = new ArrayList<Double>();
            avgList = new ArrayList<Double>();
            realCount = 0;// 实际的分时图数据条数
            showIndex = 0;// 显示的分时图最新index
//			reduce = 60000;// 分时图时间间隔
            reduce = 300000;// FIXME :分时图时间间隔
            max = 0;
            min = 0;
            kReduce = 60000; // k线间隔
            startIndex = -1;
            preSize = 0;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * 获取小数位
     *
     * @return
     */
    public int getDecimalPlace() {
        return this.decimalPlace;
    }

    /**
     * 将分时数据装载进来
     */
    public void inputTimeData() {
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.CHINA);
        try {
            Date startTime = settlementPlan.getOpenTime();
            Date endTime = settlementPlan.getReckonTime();
            int type;
            // 如果当前是横屏，使用1分钟线画分时图
            if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
                type = ChartEnums.HistoryData_Minute;
            } else {
                // 竖屏，现在也使用1分钟线 2016-11-02
                // type = MTPEnums.HistoryData_Minute5;
                type = ChartEnums.HistoryData_Minute;
            }
//            List<HistoryCycle> cycles = MarketDataTools.getHistoryCycle(goodsId, type, startTime, endTime, 0);
//            if (cycles != null && cycles.size() > 0) {
//                if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
//                    LogUtils.e("chart", "1分钟线处理");
//                    if (goodsInfo.getGoodsInfo() == ChartEnums.TRADEMODE_BIDDING) {
//                        inputTimeAndCalcData(MTPChartControl.TIME_M1, toMap(cycles));
//                    } else {
//                        inputTimeAndCalcData(MTPChartControl.TIME_M1, toMap(cycles));
//                    }
//                } else {
//                    LogUtils.e("chart", "5分钟线处理");
//                    if (goodsInfo.getTradeMode() == ChartEnums.TRADEMODE_BIDDING) {
//                        inputTimeAndCalcData(MTPChartControl.TIME_M1, toMap(cycles));
//                    } else {
//                        inputTimeAndCalcData(MTPChartControl.TIME_M1, toMap(cycles));
//                    }
//                }
//            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 将list数据转换为map数据
     *
     * @param cycles list数据
     * @return
     */
    private HashMap<String, HistoryCycle> toMap(List<HistoryCycle> cycles) {
        HashMap<String, HistoryCycle> map = new HashMap<String, HistoryCycle>();
        for (HistoryCycle historyCycle : cycles) {
            map.put(df2.format(historyCycle.getStartTime()), historyCycle);
        }
        return map;
    }

    /**
     * 获取hashmap中最大时间
     *
     * @param map
     * @return
     */
    private long getMaxTime(HashMap<String, HistoryCycle> map) {
        long maxTime = 0;
        Iterator<String> keys = map.keySet().iterator();
        while (keys.hasNext()) {
            String key = keys.next();
            HistoryCycle item = map.get(key);
            if (item == null) {
                continue;
            }
            long time = item.getStartTime().getTime();
            if (time > maxTime) {
                maxTime = time;
            }
        }
        return maxTime;
    }

    /**
     * 二分查找时间在timelist中的索引（下标）
     *
     * @param time
     * @return
     */
    private int findIndexOfTime(String time) {
        if (time == null) {
            return -1;
        }
        if (timeList == null || timeList.isEmpty()) {
            return -1;
        }
        try {
            Date timeDate = df2.parse(time);
            // 起始索引
            int index = timeList.size() / 2;
            int min = 0;
            int max = timeList.size() - 1;
            String item = timeList.get(index);
            Date itemDate = df2.parse(item);
            while (timeDate.compareTo(itemDate) != 0) {
                if (timeDate.compareTo(itemDate) > 0) {
                    // 大于index
                    min = index + 1;
                } else {
                    // 小于index
                    max = index - 1;
                }
                if (max < min) {
                    // 如果找不到可能会出现这种情况，因此返回-2
                    return -2;
                }
                // 重新计算中点
                index = min + (max - min) / 2;
                // 得到新中点转换的时间
                itemDate = df2.parse(timeList.get(index));
            }
            return index;
        } catch (ParseException e) {
            e.printStackTrace();
            return -1;
        }

    }

    private void otcInputAndCalcTimeData(String type, HashMap<String, HistoryCycle> cycles) {
        try {
            long time1 = System.currentTimeMillis();
            if (cycles == null || cycles.size() == 0) {
                return;
            }
            // 如果是使用1分钟数据，横坐标时间间隔为60000毫秒
            if (type.equals(TIME_M1)) {
                reduce = 60000;
            } else {
                // 如果是使用5分钟数据，横坐标时间间隔为300000毫秒
                reduce = 300000;
            }
            ChartDataContainer container = dataMap.get(type);
            if (container == null) {
                dataMap.put(type, new ChartDataContainer());
            }
            container = dataMap.get(type);
            timeList.clear();
            timePriceList.clear();
            avgList.clear();
            realCount = 0;
            container.mOHLCList.clear();
            Date sTime = settlementPlan.getOpenTime();
            long startTimeS = sTime.getTime();
            Date eTime = settlementPlan.getReckonTime();
            long endTimeS = eTime.getTime();
            HashMap<String, HistoryCycle> datasInSettlePlan = new HashMap<String, HistoryCycle>();
            // 筛选出在结算计划时间之内的数据，并将按时间倒序的数据顺序排列
            Iterator<String> keys = cycles.keySet().iterator();
            while (keys.hasNext()) {
                String key = keys.next();
                HistoryCycle item = cycles.get(key);
                if (item == null) {
                    continue;
                }

                if (!settlementPlan.inPlan(item.getStartTime())) {
                    continue;
                }

                datasInSettlePlan.put(key, item);
            }

            // 循环得到了时间list
            for (long time = startTimeS; time <= endTimeS; time += reduce) {
                Date dateTime = new Date(time);
                if (settlementPlan.inPlan(dateTime)) {
                    timeList.add(df2.format(dateTime));
                }
            }
            // 得到最新的一条数据
            long lastTime = getMaxTime(datasInSettlePlan);
            showIndex = findIndexOfTime(df2.format(new Date(lastTime)));
            if (showIndex < 0) {
                return;
            }
            for (int i = 0; i < timeList.size(); i++) {
                HistoryCycle item = datasInSettlePlan.get(timeList.get(i));
                if (item == null) {
                    item = new HistoryCycle();
                    if (i == 0) {
                        // 如果数据集中不存在该时间点数据，而且是开盘第一条，取昨收作为
                        // 收盘价
                        double preClosed = getPreSettle();
                        item.setOpened(preClosed);
                        item.setHighest(preClosed);
                        item.setLowest(preClosed);
                        item.setClosed(preClosed);
                        avgList.add(getPreSettle());
                    } else {
                        // 如果不是第一个，价格设置为前一时间点一致
                        double prePrice = timePriceList.get(i - 1);
                        item.setOpened(prePrice);
                        item.setHighest(prePrice);
                        item.setLowest(prePrice);
                        item.setClosed(prePrice);
                        avgList.add(avgList.get(i - 1));
                    }
                } else {
                    if (i == 0) {
                        avgList.add(item.getClosed());
                        realCount++;
                    } else {
                        avgList.add((realCount * avgList.get(i - 1) + item.getClosed()) / (realCount + 1));
                        realCount++;
                    }
                }
                timePriceList.add(item.getClosed());
                ChartData chartData = null;
                // 重用对象，如果当前item在源数据集中能找到对象，直接用
                if (i < container.mOHLCList.size()) {
                    chartData = (ChartData) container.mOHLCList.get(i);
                }

                // 否则使用新的
                if (chartData == null) {
                    container.mOHLCList.add(new ChartData(item.getOpened(), item.getHighest(), item.getLowest(), item.getClosed(), timeList
                            .get(i)));
                } else {
                    // 这是存在对象的情况
                    chartData.setOpen(item.getOpened());
                    chartData.setHigh(item.getHighest());
                    chartData.setLow(item.getLowest());
                    chartData.setClose(item.getClosed());
                    chartData.setTime(timeList.get(i));
                }
            }
            max = getMaxValue();
            min = getMinValue();
            long time2 = System.currentTimeMillis();
            LogUtils.e("timespan", (time2 - time1) + "");
            container.mSize = showIndex + 1;
            LogUtils.e("chart", lastTime + "  " + startTimeS);
            LogUtils.e("chart", container.mSize + " " + df2.format(new Date(startTimeS)) + "  " + df2.format(new Date(lastTime)));
        } catch (Exception e) {
            LogUtils.e("chart", "出错了");
        }
    }

    /**
     * 将分时数据装载进来，并计算绘制图表的时间数据和价格数据
     *
     * @param type   类型
     * @param cycles 周期数据
     */
    private void inputTimeAndCalcData(String type, HashMap<String, HistoryCycle> cycles) {
        try {
            long time1 = System.currentTimeMillis();
            if (cycles == null || cycles.size() == 0) {
                return;
            }
            // 如果是使用1分钟数据，横坐标时间间隔为60000毫秒
            if (type.equals(TIME_M1)) {
                reduce = 60000;
            } else {
                // 如果是使用5分钟数据，横坐标时间间隔为300000毫秒
                reduce = 300000;
            }
            ChartDataContainer container = dataMap.get(type);
            if (container == null) {
                dataMap.put(type, new ChartDataContainer());
            }
            container = dataMap.get(type);
            timeList.clear();
            timePriceList.clear();
            avgList.clear();
            realCount = 0;
            container.mOHLCList.clear();
            Date sTime = settlementPlan.getOpenTime();
            long startTimeS = sTime.getTime();
            Date eTime = settlementPlan.getReckonTime();
            long endTimeS = eTime.getTime();
            HashMap<String, HistoryCycle> datasInSettlePlan = new HashMap<String, HistoryCycle>();
            // 筛选出在结算计划时间之内的数据，并将按时间倒序的数据顺序排列
            Iterator<String> keys = cycles.keySet().iterator();
            while (keys.hasNext()) {
                String key = keys.next();
                HistoryCycle item = cycles.get(key);
                if (item == null) {
                    continue;
                }

                if (!settlementPlan.inPlan(item.getStartTime())) {
                    continue;
                }

                datasInSettlePlan.put(key, item);
            }

            // 循环得到了时间list fixme 这里应该可以处理下，进行补数据
            for (long time = startTimeS; time <= endTimeS; time += reduce) {
                Date dateTime = new Date(time);
                if (settlementPlan.inPlan(dateTime)) {
                    timeList.add(df2.format(dateTime));
                }
            }
            // 得到最新的一条数据 FIXME:有可能当前没有找到最新的数据
            long lastTime = getMaxTime(datasInSettlePlan);
            showIndex = findIndexOfTime(df2.format(new Date(lastTime)));
            if (showIndex < 0) {
                return;
            }
            int maxIndex = findIndexOfTime(df2.format(settlementPlan.getReckonTime()));
            for (int i = 0; i < timeList.size(); i++) {
                int dataType = -1;
                HistoryCycle item = datasInSettlePlan.get(timeList.get(i));
                if (item == null) {
                    if (i <= maxIndex) {
                        dataType = ChartData.NoneDraw;
                    }
                    // 如果在请求的数据集中有该时间点数据
                    item = new HistoryCycle();
                    if (i == 0) {
                        // 如果数据集中不存在该时间点数据，而且是开盘第一条，取昨收作为
                        // 收盘价
                        double preClosed = getPreSettle();
                        item.setOpened(preClosed);
                        item.setHighest(preClosed);
                        item.setLowest(preClosed);
                        item.setClosed(preClosed);
                        avgList.add(getPreSettle());
                    } else {
                        // 如果不是第一个，价格设置为前一时间点一致
                        double prePrice = timePriceList.get(i - 1);
                        item.setOpened(prePrice);
                        item.setHighest(prePrice);
                        item.setLowest(prePrice);
                        item.setClosed(prePrice);
                        avgList.add(avgList.get(i - 1));
                    }
                } else {
                    if (i <= maxIndex) {
                        dataType = ChartData.Perfect;
                    }
                    if (i == 0) {
                        avgList.add(item.getClosed());
                        realCount++;
                    } else {
                        avgList.add((realCount * avgList.get(i - 1) + item.getClosed()) / (realCount + 1));
                        realCount++;
                    }
                }
                timePriceList.add(item.getClosed());
                ChartData chartData = null;
                // 重用对象，如果当前item在源数据集中能找到对象，直接用
                if (i < container.mOHLCList.size()) {
                    chartData = (ChartData) container.mOHLCList.get(i);
                }

                // 否则使用新的
                if (chartData == null) {
                    container.mOHLCList.add(new ChartData(item.getOpened(), item.getHighest(), item.getLowest(), item.getClosed(), timeList
                            .get(i)));
                } else {
                    // 这是存在对象的情况
                    chartData.setOpen(item.getOpened());
                    chartData.setHigh(item.getHighest());
                    chartData.setLow(item.getLowest());
                    chartData.setClose(item.getClosed());
                    chartData.setTime(timeList.get(i));
                }
                if (dataType != -1) {
                    ((ChartData) container.mOHLCList.get(i)).setDataType(dataType);
                }
            }
            max = getMaxValue();
            min = getMinValue();
            long time2 = System.currentTimeMillis();
            LogUtils.e("timespan", (time2 - time1) + "");
            container.mSize = container.getTrustNum() + 2;
            LogUtils.e("chart", lastTime + "  " + startTimeS);
            LogUtils.e("chart", container.mSize + " " + df2.format(new Date(startTimeS)) + "  " + df2.format(new Date(lastTime)));
        } catch (Exception e) {
            LogUtils.e("chart", "出错了");
        }
    }

    public double getMaxValue() {
        if (timePriceList == null || timePriceList.isEmpty()) {
            return 0;
        }

        double max = 0;
        for (Double item : timePriceList) {
            if (item.doubleValue() > max) {
                max = item.doubleValue();
            }
        }
        return max;
    }

    public double getMinValue() {
        if (timePriceList == null || timePriceList.isEmpty()) {
            return 0;
        }

        double min = Double.MAX_VALUE;
        for (Double item : timePriceList) {
            if (item.doubleValue() < min) {
                min = item.doubleValue();
            }
        }

        return min;
    }

    /**
     * 计算分时图时间list
     *
     * @return
     */
    public List<String> getTimeLists() {
        return this.timeList;
    }

    public List<Double> getAvgLists() {
        return this.avgList;
    }

    public List<Double> getTimePriceList() {
        return this.timePriceList;
    }

    public List<Double> initMA(int days, ChartDataContainer dataContainer) {
        List<Double> MA5Values = null;
        try {
            if (days < 2) {
                return null;
            }
            if (dataContainer.mSize == 0 || dataContainer.mOHLCList.size() == 0 || dataContainer.mSize > dataContainer.mOHLCList.size())
                return null;

            MA5Values = new ArrayList<Double>();

            double sum = 0;
            double avg = 0;
            double close = 0;
            String preClose = null;
//            if (goodsInfo != null) {
//                if (goodsInfo.getTradeMode() == ChartEnums.TRADEMODE_MARKETMAKE) {
//                    if (goodsInfo.getQuoteDay() != null) {
//                        preClose = goodsInfo.getQuoteDay().getOpened();
//                    }
//                } else if (goodsInfo.getTradeMode() == ChartEnums.TRADEMODE_BIDDING) {
//                    if (goodsInfo.getQuoteDay() != null) {
//                        preClose = goodsInfo.getQuoteDay().getOpened();
//                    }
//                }
//            }
            // NumberFormat nf = Global.getNumberFormat(new
            // OTCLimitCloseControl(goodsInfo).getPriceUnit());
            if (currentTab == ChartConstant.TIME) {
                SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.CHINA);
                DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);
                String time = dataContainer.mOHLCList.get(0).getTime();
                String starttime = dateFormat.format(settlementPlan.getOpenTime());

                try {
                    long gettime = df2.parse(time).getTime();
                    String[] list = timeList.get(0).split(" ");
                    long now = (dateFormat.parse(list[0]).getTime());
                    long nowNew = df2.parse(timeList.get(0)).getTime();
                    if (nowNew < gettime && (now == dateFormat.parse(starttime).getTime())) {

                        for (long i = nowNew; i < gettime; i += 300000) {
                            // LogUtils.d(TAG, "MA5Values:" + avg);
                            avg = Double.parseDouble(preClose);
                            MA5Values.add(avg);

                        }
                    }

                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
            for (int i = 0; i < dataContainer.mSize; i++) {
                if (dataContainer.mOHLCList.size() > 0) {
                    close = dataContainer.mOHLCList.get(i).getClose();
                    if (i < days) {
                        sum = sum + close;
                        avg = sum / (i + 1f);
                    } else {
                        if (dataContainer.mOHLCList.size() >= (i - days)) {
                            sum = sum + close - dataContainer.mOHLCList.get(i - days).getClose();
                            avg = sum / days;
                        }
                    }

                    avg = Double.parseDouble(MathUtil.roundNum(avg, 3));

                    MA5Values.add(avg);
                }
            }
        } catch (Exception e) {
        }
        return MA5Values;
    }

    /**
     * 获取昨收
     *
     * @return
     */
    public double getPreClosed() {
        if (goodsInfo != null) {
            return goodsInfo.getQuoteDayData().getPreclose() == 0.0 ? goodsInfo.getQuoteDayData().getOpened() : goodsInfo.getQuoteDayData().getPreclose();
        }
        return 0;
    }

    /**
     * 获取昨收
     *
     * @return
     */
    public double getPreSettle (){
        if (goodsInfo != null) {
            return goodsInfo.getQuoteDayData().getPresettle() == 0.0 ? goodsInfo.getQuoteDayData().getOpened() : goodsInfo.getQuoteDayData().getPresettle();
        }
        return 0;
    }

    public void inputAllCycleData(int type) {
        try {
            List<HistoryCycle> cycles = null;
//                    = MarketDataTools.getHistoryCycle(goodsId, type);
            if (cycles != null && cycles.size() > 0) {
                startIndex = cycles.size() - preSize;
                preSize = cycles.size();
                if (startIndex == 0) {
                    // 说明数据条数没有改变
                    // return;
                }
                if (ChartEnums.HistoryData_Minute == type) {
                    inputCycleData(MTPChartControl.K_M1, cycles.toArray(new HistoryCycle[0]));
                } else if (ChartEnums.HistoryData_Minute5 == type) {
                    inputCycleData(MTPChartControl.K_M5, cycles.toArray(new HistoryCycle[0]));
                } else if (ChartEnums.HistoryData_Minute15 == type) {
                    inputCycleData(MTPChartControl.K_M15, cycles.toArray(new HistoryCycle[0]));
                } else if (ChartEnums.HistoryData_Minute30 == type) {
                    inputCycleData(MTPChartControl.K_M30, cycles.toArray(new HistoryCycle[0]));
                } else if (ChartEnums.HistoryData_Minute60 == type) {
                    inputCycleData(MTPChartControl.K_M60, cycles.toArray(new HistoryCycle[0]));
                } else if (ChartEnums.HistoryData_Minute120 == type) {
                    inputCycleData(MTPChartControl.K_M120, cycles.toArray(new HistoryCycle[0]));
                } else if (ChartEnums.HistoryData_Minute240 == type) {
                    inputCycleData(MTPChartControl.K_M240, cycles.toArray(new HistoryCycle[0]));
                } else if (ChartEnums.HistoryData_Day == type) {
                    inputCycleData(MTPChartControl.K_DAY, cycles.toArray(new HistoryCycle[0]));
                } else if (ChartEnums.HistoryData_Week == type) {
                    inputCycleData(MTPChartControl.K_WEEK, cycles.toArray(new HistoryCycle[0]));
                } else if (ChartEnums.HistoryData_Month == type) {
                    inputCycleData(MTPChartControl.K_MONTH, cycles.toArray(new HistoryCycle[0]));
                } else if (ChartEnums.HistoryData_Year == type) {
                    inputCycleData(MTPChartControl.K_YEAR, cycles.toArray(new HistoryCycle[0]));
                } else if (ChartEnums.HistoryData_Quarter == type) {
                    inputCycleData(MTPChartControl.K_QUARTER, cycles.toArray(new HistoryCycle[0]));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 装载周期数据
     * fixme
     * @param type 类型
     */
    public void inputCycleData(int type) {
        try {
//            List<HistoryCycle> cycles = MarketDataTools.getHistoryCycle(goodsId, type, null, null, 300);
            List<HistoryCycle> cycles = null;
            if (cycles != null && cycles.size() > 0) {
                if (ChartEnums.HistoryData_Minute == type) {
                    inputCycleData(MTPChartControl.K_M1, cycles.toArray(new HistoryCycle[0]));
                } else if (ChartEnums.HistoryData_Minute5 == type) {
                    inputCycleData(MTPChartControl.K_M5, cycles.toArray(new HistoryCycle[0]));
                } else if (ChartEnums.HistoryData_Minute30 == type) {
                    inputCycleData(MTPChartControl.K_M30, cycles.toArray(new HistoryCycle[0]));
                } else if (ChartEnums.HistoryData_Minute60 == type) {
                    inputCycleData(MTPChartControl.K_M60, cycles.toArray(new HistoryCycle[0]));
                } else if (ChartEnums.HistoryData_Minute240 == type) {
                    inputCycleData(MTPChartControl.K_M240, cycles.toArray(new HistoryCycle[0]));
                } else if (ChartEnums.HistoryData_Day == type) {
                    inputCycleData(MTPChartControl.K_DAY, cycles.toArray(new HistoryCycle[0]));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 载入周期数据
     *
     * @param type   类型
     * @param cycles 周期数据
     */
    public void inputCycleData(String type, HistoryCycle[] cycles) {
        ChartDataContainer container = dataMap.get(type);
        if (container == null) {
            return;
        }
        if (container.mOHLCList == null) {
            container.mOHLCList = new ArrayList<OHLCEntity>();
        }
        container.mOHLCList.clear();
        container.mSize = cycles.length;
        if (container.mSize == 0)
            return;

        ChartData chartData;
        DateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.CHINA);
        String time = "";
        List<OHLCEntity> tempList = new ArrayList<OHLCEntity>();
        // 此size大小做比较
        int ohlcSize = container.mOHLCList.size();
        for (int i = container.mSize - 1; i >= 0; i--) {
            HistoryCycle cycle = cycles[i];
            time = df2.format(cycle.getStartTime());
            if (container.mSize - 1 - i < ohlcSize) {
                chartData = (ChartData) container.mOHLCList.get(container.mSize - 1 - i);
                chartData.reset();
                chartData.setOpen(cycle.getOpened());
                chartData.setClose(cycle.getClosed());
                chartData.setHigh(cycle.getHighest());
                chartData.setLow(cycle.getLowest());
                chartData.setVolume(cycle.getTotleVolume() + "");
                chartData.setTime(time);
            } else {
                chartData = new ChartData(cycle.getOpened(), cycle.getHighest(), cycle.getLowest(), cycle.getClosed(), time);
                chartData.setVolume(cycle.getTotleVolume() + "");
                tempList.add(chartData);
            }
        }

        if (tempList.size() > 0) {
            container.mOHLCList.addAll(tempList);
        }
        container.mSize = container.mOHLCList.size();
        updateMinusStickData(type);
    }

    public void updateMinusStickData(String type) {
        ChartDataContainer dataContainer = dataMap.get(type);
        int size = dataContainer.mSize;
        List<OHLCEntity> ohlcList = dataContainer.mOHLCList;
        List<StickEntity> stickList = dataContainer.mStickList;
        if (size <= 0 || ohlcList.size() == 0 || size > ohlcList.size())
            return;

        double dClose = 0;
        double dEMA12 = 0;
        double dEMA26 = 0;
        double dDIF = 0;
        double dDEA = 0;
        double dMACD = 0;
        ChartData lastChartData;
        ChartData chartData;
        for (int i = 0; i < size; i++) {
            chartData = (ChartData) ohlcList.get(i);
            dClose = chartData.getClose();
            if (i == 0) {
                dEMA12 = dClose;
                dEMA26 = dClose;
                dDIF = 0;
                dDEA = 0;
                dMACD = 0;
            } else {
                lastChartData = (ChartData) ohlcList.get(i - 1);
                dEMA12 = getEMA12(lastChartData.getEMA12(), dClose);
                dEMA26 = getEMA26(lastChartData.getEMA26(), dClose);
                dDIF = getDIF(dEMA12, dEMA26);
                dDEA = getDEA(lastChartData.getDEA(), dDIF);
                dMACD = getMACD(dDIF, dDEA);
            }

            chartData.setEMA12(dEMA12);
            chartData.setEMA26(dEMA26);
            chartData.setDIF(dDIF);
            chartData.setDEA(dDEA);
            chartData.setMACD(dMACD);

            if (i < stickList.size()) {
                if (dMACD > 0) {
                    stickList.get(i).setHigh(dMACD);
                    stickList.get(i).setLow(0);
                } else {
                    stickList.get(i).setHigh(0);
                    stickList.get(i).setLow(dMACD);
                }
            } else {

                if (dMACD > 0) {
                    stickList.add(new StickEntity(dMACD, 0, 2014));
                } else {
                    stickList.add(new StickEntity(0, dMACD, 2014));
                }
            }
        }
    }

    /**
     * 触摸分时图显示开高低收
     * fixme
     * @param textView
     * @param opened
     * @param highest
     * @param lowest
     * @param closed
     */
    public void setOHLC(TextView textView, double opened, double highest, double lowest, double closed) {
        int decimalPlace = goodsInfo.getGoodsInfo().getDecimalplace();
//        textView.setText(PolApplication.getInstance().getResources().getString(R.string.mtp_chart_opened)
//                + MathUtil.roundNum(opened, decimalPlace) + " "
//                + PolApplication.getInstance().getResources().getString(R.string.mtp_chart_highest) + MathUtil.roundNum(highest, decimalPlace)
//                + " " + PolApplication.getInstance().getResources().getString(R.string.mtp_chart_lowest)
//                + MathUtil.roundNum(lowest, decimalPlace) + " "
//                + PolApplication.getInstance().getResources().getString(R.string.mtp_chart_closed) + MathUtil.roundNum(closed, decimalPlace));
//        if (opened < closed) {
//            textView.setTextColor(android.graphics.Color.RED);
//        } else if (opened > closed) {
//            textView.setTextColor(activity.getResources().getColor(R.color.p_down_color));
//        } else {
//            textView.setTextColor(getNormalTextColor());
//        }
    }

    // 图表的头数据设置
    public void setTimeText(TextView curLineTV, double m1, double avg10) {
        // if (lineTitle_gkds.getVisibility() == View.VISIBLE) {
        // return;
        // }

        curLineTV.setVisibility(View.VISIBLE);

        // lineTitle_gkds.setVisibility(View.GONE);
        NumberFormat nf = NumberFormat.getInstance();
        nf.setGroupingUsed(false);
        int decimalPlace = 2;
        if (goodsInfo != null) {
            decimalPlace = goodsInfo.getGoodsInfo().getDecimalplace();
        }
        nf.setMaximumFractionDigits(decimalPlace);
        nf.setMinimumFractionDigits(decimalPlace);
        String strM1 = nf.format(m1);
        String strAVG10 = nf.format(avg10);
        String source = "";
        source = "<font color='" + getM5Color() + "'>M5:%s </font><font color='" + getAVGColor() + "'>AVG10:%s</font>";
        String strHtml = String.format(source, strM1, strAVG10);
        curLineTV.setText(Html.fromHtml(strHtml));
        System.gc();
    }

    public void setCandleStickText(TextView candleStickTV, OHLCEntity ohlc, double ma5Val, double ma10Val, double ma15Val) {
        String source = "";
        source += "<font color='" + getMA5Color() + "'>MA5:%s </font>";
        source += "<font color='" + getMA10Color() + "'>MA10:%s </font>";
        source += "<font color='" + getMA15Color() + "'>MA15:%s</font>";
        NumberFormat nf = NumberFormat.getInstance();
        nf.setGroupingUsed(false);
        nf.setMaximumFractionDigits(decimalPlace);
        nf.setMinimumFractionDigits(decimalPlace);
        String ma5 = nf.format(ma5Val);
        String ma10 = nf.format(ma10Val);
        String ma15 = nf.format(ma15Val);
        String strHtml = String.format(source, ma5, ma10, ma15);
        candleStickTV.setText(Html.fromHtml(strHtml));
    }

    /**
     * 行情累积处理
     * fixme
     * @param onQuoteAddListener
     */
    public synchronized void appendNewQupte(OnQuoteAddListener onQuoteAddListener) {
//        if (!goodsInfo.getQuoteDayData().canUseQuote()) {
//            return;
//        }
        if (onQuoteAddListener == null) {
            return;
        }
        // // 首先得判断该笔行情是否在结算计划中，不在的话就丢弃
        // if(!settlementPlan.inPlan(goodsInfo.getQuoteDay().getLastTime())){
        // return;
        // }
        //
        try {
            String close = "";
//            close = Double.parseDouble(goodsInfo.getQuoteDayData().getPrice()) == 0 ?
//                    (currentTab == ChartConstant.TIME ? goodsInfo.getQuoteDay().getPreSettle() : goodsInfo.getQuoteDay().getPreClose()) :
//                    goodsInfo.getQuoteDay().getPrice();
            double price = Double.parseDouble(close);
            if (goodsInfo.getQuoteDayData() != null) {
                max = Math.max(price, max);
                min = Math.min(price, min);
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }

        if (currentTab == ChartConstant.TIME) {
//            if (goodsInfo.getTradeMode() == ChartEnums.TRADEMODE_BIDDING) {
//                timeChartHandle(onQuoteAddListener);
//            } else {
//                //Toast.makeText(activity, "正在处理", Toast.LENGTH_LONG).show();
//                // 做市和混合的商品处理
//                timeChartHandle(onQuoteAddListener);
//            }
        } else {
            kChartHandle(onQuoteAddListener);
        }
    }

    /**
     * fixme
     * @param onQuoteAddListener
     */
    private void otcTimeChartHandle(OnQuoteAddListener onQuoteAddListener) {
//        if (!OTCChartActivity.drwaTimeChart) {
//            return;
//        }
        long last = 0;
//                goodsInfo.getQuoteDay().getLastTime().getTime();
        // 计算行情所在周期，time - (time % recude)
        last = last - (last % reduce);
        String close = "", lastTime = "";
//        close = goodsInfo.getQuoteDay().getPrice();
        lastTime = df2.format(new Date(last));

        ChartDataContainer chartDataContaine = get();
        List<OHLCEntity> ohlcEntities = chartDataContaine.mOHLCList;
        if (ohlcEntities.isEmpty()) {
            return;
        }
        // 这是最新的显示的一根数据在timeList中的下标
        int lastShowTimeIndex = showIndex;
        // 这是最新的行情时间在timeList中的下标
        int lastTimeIndex = findIndexOfTime(lastTime);
        if (lastShowTimeIndex < 0) {
            return;
        }
        // 相减，用于判断是该丢弃还是累积还是增加还是如何等等
        int sub = lastTimeIndex - lastShowTimeIndex;

        // 1、当行情小于当前历史行情的最新时间时，
        if (sub < 0) {
            // FIXME 不用做任何处理
            return;
        } else if (sub >= 0) {// 当行情时间大于本地的时间，进行行情累计
            if (sub == 0) {// 直接在最后一笔行情的数据上累计
                ChartData chartData = (ChartData) ohlcEntities.get(chartDataContaine.mSize - 1);
                if (chartData.getClose() == Double.parseDouble(close)) {
                    return;
                }
                chartData.setClose(Double.parseDouble(close));
                if (Double.parseDouble(close) < chartData.getLow()) {
                    chartData.setLow(Double.parseDouble(close));
                }
                if (Double.parseDouble(close) > chartData.getHigh()) {
                    chartData.setHigh(Double.parseDouble(close));
                }

                // 给相对应的item赋值，并且更新均价
                Double price = timePriceList.set(chartDataContaine.mSize - 1, chartData.getClose());
                calcAvg(showIndex, price);
                onQuoteAddListener.reFreshChartAfterAdd(false, false);
            } else if (sub == 1) {// 需要新加一笔行情
                // 分时图数据的处理
                ChartData chartData = (ChartData) ohlcEntities.get(chartDataContaine.mSize);
                chartData.setOpen(Double.parseDouble(close));
                chartData.setClose(Double.parseDouble(close));
                chartData.setLow(Double.parseDouble(close));
                chartData.setHigh(Double.parseDouble(close));
                chartData.setTime(lastTime);
                // 显示的条数加1
                chartDataContaine.mSize++;
                showIndex++;
                Double price = timePriceList.get(chartDataContaine.mSize - 1);
                price = timePriceList.set(chartDataContaine.mSize - 1, chartData.getClose());
                calcAvg(showIndex, price);
                onQuoteAddListener.reFreshChartAfterAdd(false, false);
            } else if (sub > 1) { // 如果是这样的，需要重新请求一次历史行情，不需要累计
                // FIXME : 请求历史
                onQuoteAddListener.reRequestHistoryDatas();// 重新请求数据
                return;
            }
        }
    }

    /**
     * 分时图实时行情处理
     * fixme
     * @param onQuoteAddListener
     */
    private void timeChartHandle(OnQuoteAddListener onQuoteAddListener) {
//        if (!OTCChartActivity.drwaTimeChart) {
//            return;
//        }
//        long last = goodsInfo.getQuoteDayData().getLasttime();
        long last = 0;
        // 计算行情所在周期，time - (time % recude)
        last = last - (last % reduce);
        String close = "", lastTime = "";
//        close = Double.parseDouble(goodsInfo.getQuoteDay().getPrice()) == 0 ?
//                goodsInfo.getQuoteDay().getPreSettle() :
//                goodsInfo.getQuoteDay().getPrice();

//		HistoryTik tik = goodsInfo.getQuoteTik().toHistoryTik();
//		if (tik == null || (tik != null && tik.getLast() == 0)) {// 没有最新价，不需要累加；竞价/混合 ：没有成交就没有最新价。也不需要累加
//			return;
//		}
////		Toast.makeText(activity, "收到新行情 ： close" + close, Toast.LENGTH_LONG).show();
//		close = tik.getLast() + "";
        if ("0".equals(close)) {
            return;
        }
        lastTime = df2.format(new Date(last));

        ChartDataContainer chartDataContaine = get();
        List<OHLCEntity> ohlcEntities = chartDataContaine.mOHLCList;
        if (ohlcEntities.isEmpty()) {
            return;
        }
        // 这是最新的显示的一根数据在timeList中的下标
        int lastShowTimeIndex = showIndex;
        // 这是最新的行情时间在timeList中的下标
        int lastTimeIndex = findIndexOfTime(lastTime);
        if (lastShowTimeIndex < 0) {
            return;
        }
        // 相减，用于判断是该丢弃还是累积还是增加还是如何等等
        int sub = lastTimeIndex - lastShowTimeIndex;

        // 1、当行情小于当前历史行情的最新时间时，
        if (sub < 0) {
            // 如果比该笔行情的新的数据是假的，要干掉最新的数据，重新画，否则不要动
            int realIndex = lastTimeIndex;

            // 求最新的实际时间
            for (int i = lastShowTimeIndex; i <= lastTimeIndex; i++) {
                if (((ChartData) ohlcEntities.get(i)).getDataType() == ChartData.AutoDraw) {
                    continue;
                } else {
                    realIndex = i;
                }
            }
            // 这是一笔旧的行情
            if (realIndex > lastShowTimeIndex) {
                // 这里考虑需不需要查看历史有没有假数据，需不需要请求数据
                return;
            } else {
                // 这其实是一笔新行情
                // 将最新行情后面的数据都还原,并将假数据列表更新
                for (int i = lastTimeIndex; i <= lastShowTimeIndex; i++) {
                    if (lastTimeIndex < 0) {
                        continue;
                    }
                    ChartData chartData = ((ChartData) ohlcEntities.get(i));
                    chartData.setDataType(ChartData.None);
                    if (virtualIndexList.contains(i)) {
                        virtualIndexList.remove((Integer) i);
                    }
                }
                onQuoteAddListener.reFreshChartAfterAdd(false, false);
                byVirtualList(lastTimeIndex);
            }
            return;
        } else if (sub >= 0) {// 当行情时间大于本地的时间，进行行情累计
            if (sub == 0) {// 直接在最后一笔行情的数据上累计
                // 如果最新这笔数据是假的，要直接用新数据更新所有字段

                ChartData chartData = (ChartData) ohlcEntities.get(showIndex);
                if (chartData.getDataType() == ChartData.AutoDraw) {
                    // 假数据变真了
                    if (virtualIndexList.contains(lastTimeIndex)) {
                        virtualIndexList.remove((Integer) lastShowTimeIndex);
                    }
                    if (chartData.getClose() == Double.parseDouble(close)) {
                        // 尝试请求历史数据
                        chartData.setDataType(ChartData.Perfect);
                        byVirtualList(lastTimeIndex);
                        realCount++;
                        return;
                    }
                    chartData.setOpen(Double.parseDouble(close));
                    chartData.setHigh(Double.parseDouble(close));
                    chartData.setLow(Double.parseDouble(close));
                    chartData.setClose(Double.parseDouble(close));
                    chartData.setDataType(ChartData.Perfect);
                    realCount++;
                }
                byVirtualList(lastTimeIndex);
                // 无论如何要，将其设为完美数据
                chartData.setDataType(ChartData.Perfect);
                // if (chartData.getClose() == Double.parseDouble(close)) {
                // // 给相对应的item赋值，并且更新均价
                // Double price = timePriceList.set(chartDataContaine.mSize - 1,
                // chartData.getClose());
                // calcAvg(showIndex, price);
                // onQuoteAddListener.reFreshChartAfterAdd(false, false);
                // return;
                // }
                chartData.setClose(Double.parseDouble(close));
                if (Double.parseDouble(close) < chartData.getLow()) {
                    chartData.setLow(Double.parseDouble(close));
                }
                if (Double.parseDouble(close) > chartData.getHigh()) {
                    chartData.setHigh(Double.parseDouble(close));
                }

                // 给相对应的item赋值，并且更新均价
                Double price = timePriceList.set(chartDataContaine.mSize - 1, chartData.getClose());
                calcAvg(showIndex, price);
                onQuoteAddListener.reFreshChartAfterAdd(false, false);
            } else if (sub == 1) {// 需要新加一笔行情
                // 分时图数据的处理
                ChartData chartData = (ChartData) ohlcEntities.get(chartDataContaine.mSize);
                chartData.setOpen(Double.parseDouble(close));
                chartData.setClose(Double.parseDouble(close));
                chartData.setLow(Double.parseDouble(close));
                chartData.setHigh(Double.parseDouble(close));
                chartData.setDataType(ChartData.Perfect);
                chartData.setTime(lastTime);
                // 显示的条数加1
                chartDataContaine.mSize++;
                showIndex++;
                Double price = timePriceList.get(chartDataContaine.mSize - 1);
                price = timePriceList.set(chartDataContaine.mSize - 1, chartData.getClose());
                calcAvg(showIndex, price);
                onQuoteAddListener.reFreshChartAfterAdd(false, false);
                byVirtualList(lastTimeIndex);
            } else if (sub > 1) { // 如果是这样的，需要重新请求一次历史行情
                // 首先要先画一根新数据（如果请求超时或者数据为空，也是要画的，因此先画了）。
                // 取之前最新数据作为基准数据，画一段横线数据
                Double price = timePriceList.get(chartDataContaine.mSize - 1);
                for (int i = showIndex; i < lastTimeIndex; i++) {
                    ChartData item = (ChartData) chartDataContaine.mOHLCList.get(i);
                    item.setOpen(price);
                    item.setHigh(price);
                    item.setLow(price);
                    item.setClose(price);
                    item.setVolume("0");
                    item.setDataType(ChartData.AutoDraw);
                    if (!virtualIndexList.contains(i)) {
                        virtualIndexList.add(i);
                    }
                    calcAvg(i, price);
                }
                Double c = Double.parseDouble(close);
                ChartData lastChartData = (ChartData) chartDataContaine.mOHLCList.get(lastTimeIndex);
                lastChartData.setOpen(c);
                lastChartData.setHigh(c);
                lastChartData.setLow(c);
                lastChartData.setClose(c);
                lastChartData.setDataType(ChartData.Perfect);
                // 显示的条数变为最新那条数据所在索引+1
                chartDataContaine.mSize = lastTimeIndex + 1;
                showIndex = lastTimeIndex;
                realCount++;
                calcAvg(lastTimeIndex, c);
                onQuoteAddListener.reFreshChartAfterAdd(false, false);

                // 然后再做一次请求历史数据
                byVirtualList(lastTimeIndex - 1);
                return;
                /**
                 * 重新请求和修补逻辑： 当来了一笔新行情，发现缺了一段历史行情，马上请求缺失的这段历史行情，并马上
                 * 生成一根新的数据，并马上重绘，缺失的那段暂时为一条横线。实时行情按照正常逻辑 累积。请求的历史行情有几种可能性：
                 * 1.正常返回：将数据填好，重新绘制，得到完整数据，这是理想情况。 2.数据为空：已经将历史数据补好，不需要做其他操作。
                 * 3.超时：不做其他操作,考虑是否重新请求，及时不重新请求，界面要有一个可主动点击的 刷新按钮。
                 *
                 *
                 */
            }
        }
    }

    /**
     * k线图处理
     * fixme
     * @param onQuoteAddListener
     */
    private void kChartHandle(OnQuoteAddListener onQuoteAddListener) {
        try {
            long last = 0;
//                    goodsInfo.getQuoteDay().getLastTime().getTime();
            // 计算行情所在周期，time - (time % recude)
            last = last - (last % kReduce);
            ChartDataContainer chartDataContaine = get();
            List<OHLCEntity> ohlcEntities = chartDataContaine.mOHLCList;
            String close = "";
//            if (goodsInfo.getQuoteTik() == null) {
//			    close = goodsInfo.getQuoteDay().getPrice();
//            } else {
//                HistoryTik tik = goodsInfo.getQuoteTik().toHistoryTik();
//                if (tik == null || tik.getLast() == 0) {// 没有最新价，不需要累加；竞价/混合 ：没有成交就没有最新价。也不需要累加
//                    return;
//                }
//                close = tik.getLast() + "";
//            }

            if (ohlcEntities.isEmpty()) {
                Date next = new Date(last);
                ChartData chartData = new ChartData();
                chartData.setOpen(Double.parseDouble(close));
                chartData.setClose(Double.parseDouble(close));
                chartData.setLow(Double.parseDouble(close));
                chartData.setHigh(Double.parseDouble(close));
//                if (goodsInfo.getTradeMode() == ChartEnums.TRADEMODE_BIDDING) {
//                    // 如果是竞价或者混合 量也要赋值
//                    try {
//                        BidQuoteDay bidQuoteDay = (BidQuoteDay) goodsInfo.getQuoteDay();
//                        chartData.setVolume(bidQuoteDay.getLastVolume());
//                    } catch (Exception e) {
//                        // TODO Auto-generated catch block
//                        e.printStackTrace();
//                    }
//                }
                // chartData.setVolume(goodsInfo.ge);
                chartData.setTime(df2.format(next));
                chartDataContaine.mOHLCList.add(chartData);
                chartDataContaine.mSize = chartDataContaine.mOHLCList.size();
                updateMinusStickData(getType());
                onQuoteAddListener.reFreshChartAfterAdd(false, true);
                return;
            }

            OHLCEntity lastItem = ohlcEntities.get(ohlcEntities.size() - 1);
            Date lastItemTime = df2.parse(lastItem.getTime());
            long step = 8 * 60 * 60 * 1000L;
            if (last % (60 * 1000 * 60 * 24) == 0 && last - lastItemTime.getTime() > step) {
                last = last - step;
            }
            long timeSpan = last - lastItemTime.getTime();
            if (timeSpan < 0) {

            } else if (timeSpan == 0) {// 说明同一个周期内的
                ChartData chartData = (ChartData) ohlcEntities.get(ohlcEntities.size() - 1);
                // 如果行情的价格并没有变化，那么不做更新

//                if (chartData.getClose() == Double.parseDouble(close)) {
//                    if (goodsInfo.getTradeMode() == MTPEnums.TRADEMODE_BIDDING) {
//                        // 如果是竞价或者混合 量也要赋值
//                        try {
//                            BidQuoteDay bidQuoteDay = (BidQuoteDay) goodsInfo.getQuoteDay();
//                            chartData.setVolume(Double.parseDouble(bidQuoteDay.getLastVolume()) + Double.parseDouble(chartData.getVolume())
//                                    + "");
//                        } catch (Exception e) {
//                            // TODO Auto-generated catch block
//                            e.printStackTrace();
//                        }
//                        onQuoteAddListener.reFreshChartAfterAdd(false, false);
//                    }
//                    return;
//                }
                chartData.setClose(Double.parseDouble(close));
                if (Double.parseDouble(close) < chartData.getLow()) {
                    chartData.setLow(Double.parseDouble(close));
                }
                if (Double.parseDouble(close) > chartData.getHigh()) {
                    chartData.setHigh(Double.parseDouble(close));
                }
//                if (goodsInfo.getTradeMode() == ChartEnums.TRADEMODE_BIDDING) {
//                    // 如果是竞价或者混合 量也要赋值
//                    try {
//                        BidQuoteDay bidQuoteDay = (BidQuoteDay) goodsInfo.getQuoteDay();
//                        chartData.setVolume(Double.parseDouble(bidQuoteDay.getLastVolume()) + Double.parseDouble(chartData.getVolume())
//                                + "");
//                    } catch (Exception e) {
//                        // TODO Auto-generated catch block
//                        e.printStackTrace();
//                    }
//                }
                onQuoteAddListener.reFreshChartAfterAdd(false, false);
            } else if (timeSpan >= kReduce) {// 下一个周期
                // 非分时图时的处理
                // 加一个数据148063680000086400000
                // if(last % (60 * 1000 * 60 * 24) == 0){
                // last = last - 8 * 3600 * 1000;
                // }
                Date next = new Date(last);
                ChartData chartData = new ChartData();
                chartData.setOpen(Double.parseDouble(close));
                chartData.setClose(Double.parseDouble(close));
                chartData.setLow(Double.parseDouble(close));
                chartData.setHigh(Double.parseDouble(close));
//                if (goodsInfo.getTradeMode() == MTPEnums.TRADEMODE_BIDDING) {
//                    // 如果是竞价或者混合 量也要赋值
//                    try {
//                        BidQuoteDay bidQuoteDay = (BidQuoteDay) goodsInfo.getQuoteDay();
//                        chartData.setVolume(bidQuoteDay.getLastVolume());
//                    } catch (Exception e) {
//                        // TODO Auto-generated catch block
//                        e.printStackTrace();
//                    }
//                }
                // chartData.setVolume(goodsInfo.ge);
                chartData.setTime(df2.format(next));
                chartDataContaine.mOHLCList.add(chartData);
                chartDataContaine.mSize = chartDataContaine.mOHLCList.size();
                updateMinusStickData(getType());
                onQuoteAddListener.reFreshChartAfterAdd(false, false);//isNew修改成false是设置刷新会导致日K出现在中间时间段的
//                onQuoteAddListener.reFreshChartAfterAdd(false, true);
            } else {

            }

        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void loseTimeDataNull(Date startTime, Date endTime, long goodsId) {
        String startString = df2.format(startTime);
        String endString = df2.format(endTime);
        int startIndex = findIndexOfTime(startString);
        int endIndex = findIndexOfTime(endString);
        if (startIndex <= 0) {
            return;
        }
        ChartDataContainer container = get();
        double price = timePriceList.get(startIndex - 1);
        for (int i = startIndex; i <= endIndex; i++) {
            ChartData item = (ChartData) container.mOHLCList.get(i);
            item.setOpen(price);
            item.setHigh(price);
            item.setLow(price);
            item.setClose(price);
            item.setDataType(ChartData.NoneDraw);
            calcAvg(i, price);
        }
    }

    /**
     * otc商品请求丢失数据回应处理
     *
     * @param startTime
     * @param endTime
     * @param goodsId
     */
    public void otcLoseTimeDataNull(Date startTime, Date endTime, long goodsId) {
        String startString = df2.format(startTime);
        String endString = df2.format(endTime);
        int startIndex = findIndexOfTime(startString);
        int endIndex = findIndexOfTime(endString);
        if (startIndex <= 0) {
            return;
        }
        ChartDataContainer container = get();
        double price = timePriceList.get(startIndex - 1);
        for (int i = startIndex; i <= endIndex; i++) {
            ChartData item = (ChartData) container.mOHLCList.get(i);
            item.setOpen(price);
            item.setHigh(price);
            item.setLow(price);
            item.setClose(price);
            item.setDataType(ChartData.NoneDraw);
            calcAvg(i, price);
        }
    }

    /**
     * 得到了缺失的分时数据回应
     * fixme
     *
     * @param startTime
     * @param goodsId
     */
    public void loseTimeDataBack(Date startTime, Date endTime, long goodsId) {
        // 得到了分钟线数据
//        List<HistoryCycle> cycles = MarketDataTools.getHistoryCycle(goodsId, ChartEnums.HistoryData_Minute, startTime, endTime, 0);
        List<HistoryCycle> cycles = null;
        if (cycles == null || cycles.size() <= 0) {
            // 正常情况数据不应该为空，待考虑如果数据为空如何做
            timeDataNullHandle(startTime, endTime);
            return;
        }
        ChartDataContainer container = get();
        startTime.setTime(startTime.getTime() - startTime.getTime() % 60000);
        HashMap<String, HistoryCycle> map = toMap(cycles);

        // 得到最新的一条数据
        long lastTime = getMaxTime(map);
        int startIndex = findIndexOfTime(df2.format(startTime));
        int endIndex = findIndexOfTime(df2.format(endTime));
        int maxIndex = findIndexOfTime(df2.format(new Date(lastTime)));
        if (maxIndex < 0) {
            return;
        }
        for (int i = startIndex; i <= endIndex; i++) {
            HistoryCycle item = map.get(timeList.get(i));
            int dataType = -1;
            if (item == null) {
                if (i <= maxIndex) {
                    dataType = ChartData.NoneDraw;
                } else {
                    dataType = ChartData.AutoDraw;
                }
                // 如果在请求的数据集中有该时间点数据
                item = new HistoryCycle();
                if (i == 0) {
                    // 如果数据集中不存在该时间点数据，而且是开盘第一条，取昨收作为
                    // 收盘价
                    double preClosed = getPreSettle();
                    item.setOpened(preClosed);
                    item.setHighest(preClosed);
                    item.setLowest(preClosed);
                    item.setClosed(preClosed);
                    avgList.add(getPreSettle());
                } else {
                    // 如果不是第一个，价格设置为前一时间点一致
                    double prePrice = timePriceList.get(i - 1);
                    item.setOpened(prePrice);
                    item.setHighest(prePrice);
                    item.setLowest(prePrice);
                    item.setClosed(prePrice);
                    avgList.add(avgList.get(i - 1));
                }
                if (!virtualIndexList.contains(i)) {
                    virtualIndexList.add(i);
                }
            } else {
                if (i <= maxIndex) {
                    dataType = ChartData.Perfect;
                } else {
                    dataType = ChartData.AutoDraw;
                }
                if (i == 0) {
                    avgList.add(item.getClosed());
                    realCount++;
                } else {
                    avgList.add((realCount * avgList.get(i - 1) + item.getClosed()) / (realCount + 1));
                    realCount++;
                }
                if (virtualIndexList.contains(i)) {
                    virtualIndexList.remove((Integer) i);
                }
            }
            timePriceList.add(item.getClosed());
            ChartData chartData = null;
            // 重用对象，如果当前item在源数据集中能找到对象，直接用
            if (i < container.mOHLCList.size()) {
                chartData = (ChartData) container.mOHLCList.get(i);
            }

            // 否则使用新的
            if (chartData == null) {
                container.mOHLCList.add(new ChartData(item.getOpened(), item.getHighest(), item.getLowest(), item.getClosed(), timeList
                        .get(i)));
            } else {
                // 这是存在对象的情况
                chartData.setOpen(item.getOpened());
                chartData.setHigh(item.getHighest());
                chartData.setLow(item.getLowest());
                chartData.setClose(item.getClosed());
                chartData.setTime(timeList.get(i));
            }
            if (dataType != -1) {
                ((ChartData) container.mOHLCList.get(i)).setDataType(dataType);
                if (dataType == ChartData.AutoDraw) {
                    if (!virtualIndexList.contains(i)) {
                        virtualIndexList.add(i);
                    }
                } else {
                    if (virtualIndexList.contains(i)) {
                        virtualIndexList.remove((Integer) i);
                    }
                }
            }
        }
        max = getMaxValue();
        min = getMinValue();
        // calcChartDataType(map, startIndex, endIndex, container);
    }

    // 计算数据类型，这个很重要，要不要修补，怎么修补等，都基于这个数据
    private void calcChartDataType(HashMap<String, HistoryCycle> map, int startIndex, int endIndex, ChartDataContainer container) {
        long maxTime = getMaxTime(map);
        int firstIndex = findIndexOfTime(df2.format(new Date(maxTime)));
        for (int i = firstIndex; i < endIndex; i++) {
            ChartData chartData = (ChartData) container.mOHLCList.get(i);
            chartData.setDataType(ChartData.AutoDraw);
            if (!virtualIndexList.contains(i)) {
                virtualIndexList.add(i);
            }
        }

        for (int i = startIndex; i < firstIndex; i++) {
            ChartData chartData = (ChartData) container.mOHLCList.get(i);
            chartData.setDataType(ChartData.AutoDraw);
            if (chartData.getDataType() != ChartData.Perfect) {
                chartData.setDataType(ChartData.NoneDraw);
                if (virtualIndexList.contains(i)) {
                    virtualIndexList.remove((Integer) i);
                }
            }
        }
    }

    /**
     * 计算更新均线数据
     *
     * @param index
     * @param price
     */
    private void calcAvg(int index, double price) {
        if (index <= 0) {
            // 如果下标小于等于0，说明这是当日第一条行情或第一个周期，均价直接等于现价
            avgList.set(0, price);
            return;
        }
        // 取之前的数据的均价
        Double pre = avgList.get(index - 1);
        // ((pre * count) + price)/(count + 1)
        // 这里realcount是真实的周期数据条数，因此算之前的总和要减去1
        pre = (pre.doubleValue() * (realCount - 1) + price) / realCount;
        avgList.set(index, pre);
    }

//    public TradeSummaryData getSearchHoldOrder(long goodsId) {
//        List<TradeSummaryData> orders = GlobalDataCollention.getInstance().getTradePositionData();
//        if (orders == null) {
//            return null;
//        }
//        if (orders.isEmpty()) {
//            return null;
//        }
//        for (TradeSummaryData item : orders) {
//            if (item.getGoodsid() == goodsId) {
//                return item;
//            }
//        }
//        return null;
//    }

    /**
     * 计算时间差
     *
     * @param end0 最新的时间，
     * @param end1 第二新的时间() <li>"123816283612" 时间戳 现在的时间格式，如果有其他的时间格式，需要修改逻辑
     * @return
     */
    private int timeDifference(long end0, String end1, String pattern) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
        Date date0 = null;
        Date date1 = null;
        try {
            date0 = new Date(end0);
            date1 = dateFormat.parse(end1);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return (int) (date0.getTime() - date1.getTime());
    }

    /**
     * @param lastEMA12 前一日EMA（12)
     * @param close     今日收盘价
     * @brief 计算EMA（12） EMA 是MA（平滑移动平均线）的另一种形式，全名“加权指数移动平均线”。
     * EMA（12）=前一日EMA（12）×11/13＋今日收盘价×2/13.
     * 2/13就是12日移动平均线的平滑因子，他的意思是指：给予新价格 2/13的权重，给予过去的EMA 11/13的权重。
     * 第一天的EMA12等于收盘价.
     */
    public static double getEMA12(double lastEMA12, double close) {
        // return Arith.add(Arith.div(Arith.mul(lastEMA12, 11),13),
        // Arith.div(Arith.mul(close, 2),13));
        return (lastEMA12 * 11 + close * 2) / 13;
    }

    /**
     * @param lastEMA26 前一日EMA（26)
     * @param close     今日收盘价
     * @brief 计算EMA（26） EMA 是MA（平滑移动平均线）的另一种形式，全名“加权指数移动平均线”。
     * EMA（26）=前一日EMA（26）×25/27＋今日收盘价×2/27 第一天的EMA26等于收盘价.
     */
    public static double getEMA26(double lastEMA26, double close) {
        // return Arith.add(Arith.div(Arith.mul(lastEMA26, 25),27),
        // Arith.div(Arith.mul(close, 2),27));
        return (lastEMA26 * 25 + close * 2) / 27;
    }

    /**
     * @param EMA12 今日EMA（12)
     * @param EMA26 今日EMA（26）
     * @brief 计算DIF DIF=今日EMA（12）－今日EMA（26）
     */
    public static double getDIF(double EMA12, double EMA26) {
        // return Arith.sub(EMA12, EMA26);
        return EMA12 - EMA26;
    }

    /**
     * @param lastDEA 前一日DEA
     * @param DIF     今日DIF
     * @brief 计算DIF的9日EMA （DEA）
     * 根据离差值计算其9日的EMA，即离差平均值，是所求的MACD值。为了不与指标原名相混淆，此值又名DEA或DEM。
     * 今日DEA（MACD）=前一日DEA×8/10＋今日DIF×2/10
     */
    public static double getDEA(double lastDEA, double DIF) {
        // return Arith.add(Arith.div(Arith.mul(lastDEA, 8),10),
        // Arith.div(Arith.mul(DIF, 2),10));
        return (lastDEA * 8 + DIF * 2) / 10;
    }

    /**
     * @param DIF 今日DIF
     * @param DEA 今日DEA
     * @brief 计算MACD MACD=BAR=2×(DIF－DEA)
     */
    public static double getMACD(double DIF, double DEA) {
        // return Arith.mul(2, Arith.sub(DIF,DEA));
        return 2 * (DIF - DEA);
    }

    public GoodsInfoAndQuotes getGoodsInfo() {
        return goodsInfo;
    }

    public void setGoodsInfo(GoodsInfoAndQuotes goodsInfo) {
        this.goodsInfo = goodsInfo;
    }
}
