package jtznyj.engineer.service.winform.data;

import jtznyj.engineer.service.dataDiagnosticService.data.*;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import jtznyj.engineer.service.dataDiagnosticService.DataDiagnosticEngineer;
import jtznyj.engineer.service.dataDiagnosticService.models.DoorList;
import jtznyj.engineer.service.winform.data.mcp_.SecValue;

import java.text.DecimalFormat;
import java.util.*;

import static jtznyj.engineer.service.dataDiagnosticService.WellTrendDataDiagnostic.*;
import static jtznyj.engineer.service.winform.CheckEngineerWarning.getRealFieldName;

/**
 * 监测曲线参数
 */
public class MonitorCurverParam {
    /**
     *字段可用性
     */
    public boolean _fieldUseable = true;

    /**
     * 条件组合运算类别（and\or）
     */
    public FieldHandleType _fieldHandleType = FieldHandleType.FHT_And;

    /**
     * 趋势参数分类--按总量、按倍数
     */
    public TrendTypeParam _trendTypeParam = TrendTypeParam.TT_TOTALNUM;

    /**
     * 趋势分析--起始值
     */
    public double _beginValue = 0.0;

    /**
     * 趋势分析--截止值
     */
    public double _endValue = 0.0;

    /**
     * 分组编号
     */
    public int _fzNum = 0;

    /**
     * 总量
     */
    public double _totalNum = 1.0;

    /**
     * 倍数
     */
    public double _mul = 1.0;

    /**
     * 波动范围
     */
    public double _bdLtValue = 0.1;

    /**
     * 分析类别--1门限 2振幅 4趋势辨别 8波动
     */
    public AnalyseType _analyseType = AnalyseType.AT_MinMax;

    /**
     * 趋势分析类别
     */
    public TrendType _trendType = TrendType.TT_Stable;

    /**
     * 规则名
     */
    public String _name = "";
    public SecondState _secondState;

    /**
     * 原始字段配置--用户维护的字段
     */
    public String _originalField = "";

    /**
     * 真实字段
     */
    public String _realField = "";
    /**
     * 开泵
     */
    public boolean _isPumpRunJump = false;

    /**
     * 开泵时长
     */
    public int _isPumpRunJumpTime = 30;

    /**
     * 停泵
     */
    public boolean _isPumpStopJump = false;

    /**
     * 停泵时长
     */
    public int _isPumpStopJumpTime = 30;
    /**
     * 是否排除气体
     */
    public boolean _pchx = false;
    /**
     * 排气时长
     */
    public int _pchxTime = 60;

    /**
     * 监控时长
     */
    public double _monitorTime = 60.0;

    /**
     * 是否低于正常值
     */
    public boolean _continue = false;

    /**
     * 正常值
     */
    public double _continueValue = 0.0;

    /**
     * 异常持续时长
     */
    public double _continuedTime = 60.0;

    /**
     * 门限--最小总量
     */
    public double _minTotalNum = 0.0;

    /**
     * 门限--最大总量
     */
    public double _maxTotalNum = 100.0;

    /**
     * 与振幅数量有关的--震荡次数
     */
    public int _zdCount = 1;

    /**
     * 振幅数据集
     */
    private volatile ArrayList<MonitorAngle> _listMonitorRangeAngles = new ArrayList<MonitorAngle>();

    /**
     * 最后一个点时间--没用
     */
    private Date _dtLastLowValueTime;

    /**
     * 是否启用前置条件
     */
    public Boolean preconditions =false;
    /**
     * 前置条件判断字段
     */
    public String preconditionsField = "";
    /**
     * 前置条件list
     */
    public ArrayList<DoorList> doorList = new ArrayList<>();

    // endregion
    private volatile ArrayList<TimeValue> _listTimeValues = new ArrayList<>();

    public static Comparator<MonitorCurverParam> McpSortByGroupNum = (mcp0, mcp1) -> {
        int result;
        if (mcp0._fzNum > mcp1._fzNum) {
            result = 1;
        } else if (mcp0._fzNum == mcp1._fzNum) {
            result = 0;
        } else {
            result = -1;
        }
        return result;
    };

    private void AddTimeValue(Hashtable record) {
        if (record != null && StringUtils.isNotEmpty(_realField)) {
            //确保监控数据都在监控时间范围之内
            Date dt = (Date) record.get(MonitorContext.fieldTime);
            if(this._monitorTime>0){
                if(this._listTimeValues.size()>0){
                    //时差
                    int totalSeconds = Math.abs((int) ((dt.getTime() - _listTimeValues.get(0)._dateTime.getTime()) / 1000));
                    if(totalSeconds>this._monitorTime){
                        //超过了监控时间范围
                        this._listTimeValues.remove(0);
                    }
                }
            }
            TimeValue tv = new TimeValue(dt,
                    (double) record.get(this._originalField),
                    (double) record.get(MonitorContext.fieldScjs),
                    (double) record.get(MonitorContext.fieldZtwz));
//            mutex.WaitOne();
            this._listTimeValues.add(tv);
//            mutex.ReleaseMutex();
        }
    }

    private void AddAngleTimeValue(Hashtable record) {
        if (record != null && StringUtils.isNotEmpty(_realField)) {
            //确保监控数据都在监控时间范围之内
            Date dt = (Date) record.get(MonitorContext.fieldTime);
            if(this._monitorTime>0){
                if(this._listMonitorRangeAngles.size()>0){
                    //时差
                    int totalSeconds = Math.abs((int) ((dt.getTime() - _listMonitorRangeAngles.get(0)._dtCurrent.getTime()) / 1000));
                    if(totalSeconds>this._monitorTime){
                        //超过了监控时间范围
                        this._listMonitorRangeAngles.remove(0);
                    }
                }
            }
            if(this._listTimeValues.size()>2){
                int lastIndex = this._listTimeValues.size() - 1;
                MonitorPoint mp0 = new MonitorPoint(0.0, this._listTimeValues.get(lastIndex - 2)._value);
                MonitorPoint mpAngle = new MonitorPoint((this._listTimeValues.get(lastIndex - 1)._dateTime.getTime() - this._listTimeValues.get(lastIndex - 2)._dateTime.getTime()) / 1000,
                        this._listTimeValues.get(lastIndex - 1)._value);
                MonitorPoint mp = new MonitorPoint((this._listTimeValues.get(lastIndex)._dateTime.getTime() - this._listTimeValues.get(lastIndex - 1)._dateTime.getTime()) / 1000,
                        this._listTimeValues.get(lastIndex)._value);
                double angle = MonitorAngle.CalcAngle(mp0, mpAngle, mp);
                MonitorAngle ma = new MonitorAngle(angle, Math.abs(mpAngle._x), mpAngle._y, this._listTimeValues.get(lastIndex - 1)._dateTime);
                this._listMonitorRangeAngles.add(ma);
            }

//            mutex.WaitOne();
//            mutex.ReleaseMutex();
        }
    }

    /**
     * 清空所有监控样本数据
     */
    public void ResetMonitorParams() {
//        mutex.WaitOne();
        this._listTimeValues.clear();
        // TODO: 1
        this._listMonitorRangeAngles.clear();
//        mutex.ReleaseMutex();
    }

    /**
     * 获得钻机状态信息
     * @return
     */
    public DrillStateResult GetDrillState(RecordHashTable _prevDrillStateData, RecordHashTable record) {
        DrillStateResult result = new DrillStateResult();

        boolean currentIsPumpRun;
        //时间
        //泵冲1(SPM)
        double bc = (double) record.get(MonitorContext.fieldBc1);
        //泵冲2(SPM)
        double bc2 = (double) record.get(MonitorContext.fieldBc2);
        //泵冲3(SPM)
        double bc3 = (double) record.get(MonitorContext.fieldBc3);
        //钻头位置(m)
        double ztwz = (double) record.get(MonitorContext.fieldZtwz);
        //实测井深(M)
        double js = (double) record.get(MonitorContext.fieldScjs);

        //fieldCdsj = "迟到时间";

        //大钩高度(m)
        double dggd = (double) record.get(MonitorContext.fieldDggd);
        //大钩负荷(kN)
        double dgfh = (double) record.get(MonitorContext.fieldDgfh);
        //立压(MPa)
        double ly = (double) record.get(MonitorContext.fieldLy);
        //转速(RPM)
        double zpzs = (double) record.get(MonitorContext.fieldZpzs);

        //fieldZtjc = "Temp5";
        //默认也是没有对应的字段
        double ztjc = 0.0;
        try {
            ztjc = (double) record.get(MonitorContext.fieldZtjc);
        } catch (Exception ex_C0) {
        }
        double bc4 = bc + bc2 + bc3;
        double zqmx = 15.0;
        zqmx *= 9.8;
        double bcmx = 1.0;
        double qxzcd = 27.0;
        //开泵条件
        currentIsPumpRun = (bc > bcmx || bc2 > bcmx || bc3 > bcmx);
        boolean bZpRun = zpzs > 0.001;
        boolean bZtjc = ztjc > 0.001;

        boolean bQxzRange = Math.abs(ztwz - js) < qxzcd;//Math.abs(钻头位置-实测井深)
        DrillState curDrillState;
        if (_prevDrillStateData == null) {
            //默认第一条是停钻状态
            curDrillState = DrillState.Stop;
        } else {
            //上一钻头位置
            double prevZtwz = (double) _prevDrillStateData.get(MonitorContext.fieldZtwz);
            //上一大钩高度
            double prevDggd = (double) _prevDrillStateData.get(MonitorContext.fieldDggd);
            boolean bZj = ztwz - prevZtwz > 0.0;
            boolean bDgDown = prevDggd - dggd > 0.0;
            double dAbsZtwz = Math.abs(ztwz - prevZtwz);
            //判断大钩负荷和zqmx关系
            if (dgfh < zqmx) {
                //钻机状态--卡坐
                curDrillState = DrillState.TakePipe;
                if (currentIsPumpRun) {
                    //如果是开泵状态，则钻机状态处于循环状态
                    curDrillState = DrillState.Circulate;
                }
            } else if (currentIsPumpRun && (bZpRun || bZtjc) && bQxzRange) {
                double subZtjs = ztwz - js;
                if (Math.abs(subZtjs) < 0.1 || bZtjc) {
                    curDrillState = DrillState.Drilling;
                } else {
                    curDrillState = DrillState.ClearHole;
                }
            } else if (dAbsZtwz < 1E-05) {
                if (currentIsPumpRun) {
                    if (bZpRun) {
                        curDrillState = DrillState.ClearHole;
                    } else {
                        curDrillState = DrillState.Circulate;
                    }
                } else if (bDgDown) {
                    curDrillState = DrillState.Trip;
                } else {
                    curDrillState = DrillState.DrillDown;
                }
            } else if (currentIsPumpRun) {
                curDrillState = DrillState.Circulate;
            } else if (ztwz - prevZtwz >= 0.0) {
                curDrillState = DrillState.DrillDown;
            } else {
                curDrillState = DrillState.Trip;
            }
        }
        //不必克隆数据
        result.state = curDrillState;
        result.isPumpRun = currentIsPumpRun;
        return result;
    }

    /**
     * 根据一个具体诊断模型诊断给定的一段数据
     * @return 返回值 false:没有异常 true:有异常
     */
    public CurverAnalyseResult doPerformAnalyse(List<RecordHashTable> dataList) {
        boolean _isPumpRun = true;
        //钻机状态
        DrillState drillState = DrillState.None;
        ArrayList<CurverAnalyseResult> list = new ArrayList<>();
        CurverAnalyseResult analyseResult = null;
        Date _dtPumpRunTime = new Date();
        Date _dtPumpStopTime = new Date();
        RecordHashTable prevDrillStateData = null;
        for (RecordHashTable dataItem : dataList) {
            boolean currentIsPumpRun = false;
            DrillStateResult temp = this.GetDrillState(prevDrillStateData,dataItem);
            prevDrillStateData = dataItem;

            drillState = temp.state;
            //当前是否开泵
            currentIsPumpRun = temp.isPumpRun;
            if (prevDrillStateData == null) {
                _dtPumpRunTime =  (Date) dataItem.get(MonitorContext.fieldTime);
                _dtPumpStopTime = (Date) dataItem.get(MonitorContext.fieldTime);
            }
            if (_isPumpRun != currentIsPumpRun) {
                if (currentIsPumpRun) {
                    _dtPumpRunTime = (Date) dataItem.get(MonitorContext.fieldTime);
                } else {
                    _dtPumpStopTime = (Date) dataItem.get(MonitorContext.fieldTime);
                }
            }
            _isPumpRun = currentIsPumpRun;
            analyseResult = this.CurverAnalyse(dataItem, _isPumpRun, drillState, _dtPumpRunTime, _dtPumpStopTime);



            if(analyseResult.result){
//                list.add(analyseResult);
                break;
            }
            //根据监控监控时间调整数据
            //this.AdjustDataByMonitorTime();
        }


        return analyseResult;
    }


    /**
     * 单一模型诊断分析
     * @param record
     * @param currentPumpState
     * @param drillState
     * @param lastPumpRunTime
     * @param lastPumpStopTime
     * @return
     */
    public CurverAnalyseResult CurverAnalyse(Hashtable record, boolean currentPumpState, DrillState drillState, Date lastPumpRunTime,
                                             Date lastPumpStopTime) {
        double percent = 0.0;
        this._secondState = new SecondState(this._name);
        this._secondState.SetAlarm(false);

        String idInfo = "";
        try {
            idInfo = DataDiagnosticEngineer.getFieldUnit(_realField);
        }catch (Exception e){

        }



        boolean resetAllParams = false;
        MonitorDescription description = new MonitorDescription();
        description._realField = this._realField;

        boolean state;
        CurverAnalyseResult analyseResult = new CurverAnalyseResult();
        analyseResult.md = description;
        analyseResult.resetAllParams = resetAllParams;
        analyseResult.percent = percent;
        if (record == null) {
            analyseResult.result = false;
            analyseResult.percent = percent;
            return analyseResult;
        }

        //当前值
        double v1 = (double)record.get(this._originalField);
        if(v1 < 0 ){
            analyseResult.result = false;
            analyseResult.percent = percent;
            return analyseResult;
        }

        //前置条件
        if(this.preconditions &&  StringUtils.isNotEmpty(this.preconditionsField)){
            double v = (double) record.get(getRealFieldName(this.preconditionsField));
            if(v<0){
                analyseResult.result = false;
                analyseResult.percent = percent;
                return analyseResult;
            }
        }

        this.AddTimeValue(record);
        Date dtCurrent = (Date)record.get(MonitorContext.fieldTime);
        if (this._isPumpRunJump) {   //已开泵
            double sec = Math.abs((dtCurrent.getTime() - lastPumpRunTime.getTime()) / 1000);
            if (sec < (double) this._isPumpRunJumpTime) {
                this.ResetMonitorParams();
                analyseResult.result = false;
                analyseResult.percent = percent;
                return analyseResult;
            }
        }
        if (this._isPumpStopJump) {
            //停泵
            double sec = Math.abs((dtCurrent.getTime() - lastPumpStopTime.getTime()) / 1000);
            if (sec < (double) this._isPumpStopJumpTime) {
                this.ResetMonitorParams();
                analyseResult.result = false;
                analyseResult.percent = percent;
                return analyseResult;
            }
        }
        if (this._pchx) {
            //排除气体
            try {
                boolean bHx;
                if (currentPumpState && drillState == DrillState.Drilling) {
                    //迟到时间
                    int cdsj = 0;
                    try {
                        if(record.get(MonitorContext.fieldCdsj)!=null){
                            cdsj = Integer.parseInt(record.get(MonitorContext.fieldCdsj).toString().trim());
                        }
                    } catch (Exception ex) {
                    }
                    bHx = (Math.abs(dtCurrent.getTime() - lastPumpRunTime.getTime()) / 1000 < (double) ((cdsj + this._pchxTime) * 60));
                } else {
                    bHx = true;
                }
                if (bHx) {
                    this.ResetMonitorParams();
                    analyseResult.result = false;
                    analyseResult.percent = percent;
                    return analyseResult;
                }
            } catch (Exception ex) {
            }
        }
        if (this._listTimeValues.size() == 0) {
            state = false;
        } else {
            //int nlastTime = this._listTimeValues.size() - 1;
            //Date dtMonitorBeginTime = DateUtils.addSeconds(this._listTimeValues.get(nlastTime)._dateTime, (int) (-1.0 * this._monitorTime));
            int upTotalCount = 0;
            double upTotalSec = 0.0;
            ArrayList<SecValue> listUpSecValues = new ArrayList<SecValue>();
            double upStepValue = 0.0;
            int downTotalCount = 0;
            double downTotalSec = 0.0;
            ArrayList<SecValue> listDownSecValues = new ArrayList<SecValue>();
            double downStepValue = 0.0;

            TimeValue currentTimeValue = null;
            TimeValue prevTimeValue = null;

            /**
             * 第一个时间点数据值
             */
            TimeValue tvStep = this._listTimeValues.get(0);
            double stepCompareUpDownValue = 0.0;

            DecimalFormat decimalFormat = new DecimalFormat("###################.###########");
            DecimalFormat valueDf = new DecimalFormat("0.00");
            //趋势判断
            if (this._analyseType == AnalyseType.AT_Trend && (this._trendType == TrendType.TT_Down || this._trendType == TrendType.TT_Up)) {
                //==============================================================================================
                //趋势分析--上升或者下降--begin
                for (int i = 1; i < this._listTimeValues.size(); i++) {
                    currentTimeValue = this._listTimeValues.get(i);
                    prevTimeValue = this._listTimeValues.get(i - 1);
                    //两个时间点的时间间隔（秒）
                    int totalSeconds = (int) Math.abs( ((currentTimeValue._dateTime.getTime() - prevTimeValue._dateTime.getTime()) / 1000));
                    stepCompareUpDownValue = currentTimeValue._value - tvStep._value;
                    int prevUpCount = upTotalCount;
                    int prevDownCount = downTotalCount;
                    //判断上升还是下降
                    if (stepCompareUpDownValue > 0.0) {
                        //上升
                        upTotalSec += totalSeconds;
                        upTotalCount++;
                    } else {
                        //下降
                        downTotalSec += totalSeconds;
                        downTotalCount++;
                    }
                    //上升
                    if (prevUpCount != upTotalCount) {
                        upStepValue += currentTimeValue._value - prevTimeValue._value;
                        listUpSecValues = this.UpdateLastSecValues(listUpSecValues, new SecValue(upTotalSec, upStepValue, tvStep._dateTime, currentTimeValue._dateTime));
                        listDownSecValues.clear();
                    } else {
                        //没有上升，重置上升变量
                        upStepValue = 0.0;
                        upTotalCount = 0;
                        upTotalSec = 0.0;
                    }

                    //下降
                    if (prevDownCount != downTotalCount) {
                        downStepValue += currentTimeValue._value - prevTimeValue._value;
                        listDownSecValues = this.UpdateLastSecValues(listDownSecValues, new SecValue(downTotalSec, downStepValue, tvStep._dateTime, currentTimeValue._dateTime));
                        listUpSecValues.clear();
                    } else {
                        //没有下降，重置下降变量
                        downStepValue = 0.0;
                        downTotalCount = 0;
                        downTotalSec = 0.0;
                    }
                }
                //趋势分析--上升或者下降--end
                //==============================================================================================
            } else if (this._analyseType == AnalyseType.AT_Range) {
                //=======================================================================
                //振幅分析
                this.AddAngleTimeValue(record);
            }
            if (this._listTimeValues.size() >= 1) {
                //最后一个点的时间--没用
                this._dtLastLowValueTime = this._listTimeValues.get(this._listTimeValues.size() - 1)._dateTime;
            }
            //判断是否低于正常值
            if (this._listTimeValues.size() >= 1 && this._continue && this._listTimeValues.get(this._listTimeValues.size() - 1)._value < this._continueValue) {
                this.ResetMonitorParams();
                //重置所有参数
                analyseResult.resetAllParams = true;
                state = false;
            } else {
                AnalyseType analyseType = this._analyseType;
                double dAllSec;
                switch (analyseType) {
                    case AT_MinMax:
                    case UNKnown:
                        //判断前置条件
                        if(this.preconditions &&  StringUtils.isNotEmpty(this.preconditionsField) && this.doorList.size()>0){
                            int iCount = this.doorList.size();
                            //前置条件
                            double conditionValue = (double) record.get(getRealFieldName(this.preconditionsField));

                            double rValue = (double)record.get(this._originalField);
                            //double disValue;
                            DoorList curDoorList;
                            boolean boolbfb,boolzf,boolqj;//百分比、振幅条件、普通区间[0,1200]
                            if(conditionValue != DOUBLE_NULL_VALUE && rValue != DOUBLE_NULL_VALUE){
                                for (int i = 0; i < iCount; i++) {
                                    curDoorList = this.doorList.get(i);
                                    //在指定的范围区间
                                    if(conditionValue>curDoorList.preconditionMin && conditionValue<=curDoorList.preconditionMax){
                                        if(rValue>curDoorList.ruleMin && rValue<=curDoorList.ruleMax){
                                            return analyseResult;
                                        }

                                        if(!curDoorList.isAmplification && !curDoorList.isPercentage){
                                            continue;
                                        }
                                        //disValue = Math.abs((rValue - conditionValue));
                                        //振幅
                                        boolzf = (curDoorList.isAmplification && (curDoorList.ruleMin-rValue)> Math.abs(curDoorList.amplification)) ||
                                                (curDoorList.isAmplification && (rValue-curDoorList.ruleMax)> Math.abs(curDoorList.amplification));
                                        //百分比
                                        boolbfb =curDoorList.isPercentage && Math.abs(curDoorList.ruleMax-rValue)>curDoorList.ruleMax*curDoorList.percentage /100.0;
                                        boolqj = (!curDoorList.isPercentage)&&(!curDoorList.isAmplification) && ((curDoorList.ruleMax-rValue>0));
                                        if(boolzf||boolbfb||boolqj){
                                            description._name = this._name;
                                            description._realField = this._realField;

                                            description._dtStart = _listMonitorRangeAngles.size()>0? this._listMonitorRangeAngles.get(0)._dtCurrent: null;
                                            description._dtEnd = _listMonitorRangeAngles.size()>0? this._listMonitorRangeAngles.get(0)._dtCurrent: null;
                                            //description._dtStart = tvMinMax0.getDateTime();
                                            //description.alarmDate = new Date(record.get().getTime());
                                            //description._startValue = tvMinMax0.getValue();
                                            description._startValue = rValue;
                                            description._dtStart = (Date) record.get(MonitorContext.fieldTime);
                                            description._startDepth = getWellDepth(record);
                                            description._startZtDepth = getDrillDepth(record);

                                            this._secondState._valueMin = curDoorList.ruleMin;
                                            this._secondState._valueMax = curDoorList.ruleMax;
                                            this._secondState._value0 = rValue;

                                            this._secondState.SetAlarm(true);

                                            analyseResult.result = true;
                                            String sName = DataDiagnosticEngineer.getRealFieldName(this.preconditionsField);
                                            description.lx = sName  + conditionValue + DataDiagnosticEngineer.getFieldUnit(this.preconditionsField) + "," + DataDiagnosticEngineer.getRealFieldName(this._originalField)  + rValue + DataDiagnosticEngineer.getFieldUnit(this._originalField) + "超过设定值"+decimalFormat.format(curDoorList.ruleMax)
                                                    + DataDiagnosticEngineer.getFieldUnit(this._originalField);
                                            if(curDoorList.isAmplification && boolzf){
                                                description.lx = description.lx + "(+" + decimalFormat.format(curDoorList.amplification) + DataDiagnosticEngineer.getFieldUnit(this._originalField)+ ")";
                                            }
                                            else if(curDoorList.isPercentage && boolbfb){
                                                description.lx = description.lx + "(+" + decimalFormat.format(curDoorList.percentage) + "%)";
                                            }

                                            //+"("+  decimalFormat.format(curDoorList.ruleMin)+ "-"+ decimalFormat.format(curDoorList.ruleMax) + DataDiagnosticEngineer.getFieldUnit(this._originalField) +")" ;
                                            this._secondState.SetAlarm(true);
                                            description._secondState = this._secondState.Clone();
                                            return analyseResult;
                                        }

                                        return analyseResult;
                                    }
                                }
                            }
                            analyseResult.result = false;
                            return analyseResult;
                        }
                        //================================================
                        //门限分析--begin
                        double dValue = 0.0;
                        dAllSec = 0.0;
                        TimeValue tvMinMax0 = null;
                        TimeValue tvMinMax = null;
                        for (int i = 1; i < this._listTimeValues.size(); i++) {
                            dValue = this._listTimeValues.get(i)._value;
                            if (dValue > this._maxTotalNum || dValue < this._minTotalNum) {
                                //区间之外属于异常情况
                                if (prevTimeValue == null) {
                                    tvMinMax0 = tvStep;
                                }
                                tvMinMax = this._listTimeValues.get(i);
                                dAllSec += (int)(Math.abs(this._listTimeValues.get(i)._dateTime.getTime() - this._listTimeValues.get(i - 1)._dateTime.getTime()) / 1000);
                            } else {
                                dAllSec = 0.0;
                            }
                        }
                        //异常时长与持续时长比值
                        percent = dAllSec / this._continuedTime;
                        if (this._listTimeValues.size() > 0) {
                            int last = this._listTimeValues.size() - 1;
                            this._secondState.SetMinMax(this._listTimeValues.get(0)._dateTime, this._listTimeValues.get(last)._dateTime,
                                    this._minTotalNum, this._maxTotalNum, dValue);
                        }

                        //门限分析关键的判断条件，得出结论
                        if (this._listTimeValues.size() > 0 && dAllSec > this._continuedTime) {
                            description._name = this._name;
                            description._dtStart = tvMinMax0._dateTime;
                            description._dtEnd = tvMinMax._dateTime;
                            description._startValue = tvMinMax0._value;
                            description._endValue = tvMinMax._value;
                            description._startDepth = tvMinMax0._depth;
                            description._startZtDepth = tvMinMax0._ztDepth;
                            description._endDepth = tvMinMax._depth;
                            description._endZtDepth = tvMinMax._ztDepth;
                            description.lx = "超出门限设置" +"("+  decimalFormat.format(this._minTotalNum)+ "-"
                                    + decimalFormat.format(this._maxTotalNum) + idInfo +") , 当前值"
                                    + valueDf.format(tvMinMax._value) +idInfo;
                            this._secondState.SetAlarm(true);
                            description._secondState = this._secondState.Clone();

                            analyseResult.result = true;
                            analyseResult.percent = percent;
                            return analyseResult;
                        }
                        //门限分析--end
                        //================================================

                        break;
                    case AT_Range: {
                        //================================================
                        //振幅分析--begin
                        int angleCount = 0;
                        dAllSec = 0.0;
                        MonitorAngle ma;
                        for (int j = 0; j < this._listMonitorRangeAngles.size(); j++) {
                            ma = this._listMonitorRangeAngles.get(j);
                            //45~135
                            //30~150
                            //40~140
                            if (ma._angle > 40.0 && ma._angle < 140.0) {
                                angleCount++;
                            }
                            dAllSec += ma._sec;
                        }
                        if (this._listTimeValues.size() > 0) {
                            int lastIndex = this._listTimeValues.size() - 1;
                            this._secondState.SetRange(this._listTimeValues.get(0)._dateTime, this._listTimeValues.get(lastIndex)._dateTime, angleCount);
                        }
                        boolean bRet = false;
                        //振幅分析关键的判断条件，得出结论
                        if (this._listMonitorRangeAngles.size() > 0 && angleCount > this._zdCount && dAllSec > this._continuedTime) {
                            bRet = true;
                            ma = this._listMonitorRangeAngles.get(_listMonitorRangeAngles.size()-1);
                            description._name = this._name;
                            description._dtStart = this._listMonitorRangeAngles.get(0)._dtCurrent;
                            description._dtEnd = ma._dtCurrent;
                            description._startValue = this._listMonitorRangeAngles.get(0)._value;
                            description._endValue = ma._value;
                            int last = this._listTimeValues.size() - 1;
                            description._startDepth = this._listTimeValues.get(0)._depth;
                            description._startZtDepth = this._listTimeValues.get(0)._ztDepth;
                            description._endDepth = this._listTimeValues.get(last)._depth;
                            description._endZtDepth = this._listTimeValues.get(last)._ztDepth;
                            description.lx = "超出振幅设置" +"(大于"+ this._zdCount +"次) , 当前次数" +angleCount +"次";
                            this._secondState.SetAlarm(bRet);
                            description._secondState = (SecondState) this._secondState.Clone();

                        }
                        state = bRet;
                        analyseResult.result = state;
                        analyseResult.percent = percent;
                        return analyseResult;
                        //振幅分析--end
                        //================================================
                    }
                    case AT_Trend:
                        //================================================
                        //趋势分析
                        if (this._listTimeValues.size() > 0) {
                            int last = this._listTimeValues.size() - 1;
                            this._secondState.SetTrend(this._listTimeValues.get(0)._dateTime,
                                    this._listTimeValues.get(last)._dateTime, this._listTimeValues.get(0)._value, this._listTimeValues.get(last)._value);
                        }
                        switch (this._trendType) {
                            case TT_Up:
                                //上升趋势
                                if (this._listTimeValues.size() >= 1) {
                                    if (listUpSecValues.size() > 0) {
                                        int last = listUpSecValues.size() - 1;
                                        SecValue sv = listUpSecValues.get(last);
                                        percent = sv._sec / this._continuedTime;
                                        boolean bCmpResult = false;
                                        if (this._trendTypeParam == TrendTypeParam.TT_TOTALNUM) {
                                            bCmpResult = (stepCompareUpDownValue > this._totalNum);
                                        } else if (this._beginValue <= currentTimeValue._value && currentTimeValue._value <= this._endValue) {
                                            bCmpResult = (currentTimeValue._value > tvStep._value * this._mul);
                                        }
                                        if (bCmpResult && sv._sec > this._continuedTime && tvStep._value > this._continueValue && sv._value > this._continueValue) {
                                            description._name = this._name;
                                            description._dtStart = tvStep._dateTime;
                                            description._dtEnd = sv._endTime;
                                            description._startValue = tvStep._value;
                                            description._endValue = currentTimeValue._value;
                                            description._startDepth = tvStep._depth;
                                            description._startZtDepth = tvStep._ztDepth;
                                            description._endDepth = currentTimeValue._depth;

                                            if(this._trendTypeParam == TrendTypeParam.TT_TOTALNUM){
                                                //按总量
                                                description.lx = "符合上升异常趋势(总量:" + decimalFormat.format(this._totalNum) + idInfo + " ,当前值: " + valueDf.format(currentTimeValue._value) +idInfo + ").";
                                            }else{
                                                //按倍数
                                                description.lx = "符合上升异常趋势(倍数:" + decimalFormat.format(this._mul) + "倍 , 当前值:"+  valueDf.format(currentTimeValue._value) +").";
                                            }

                                            description._endZtDepth = currentTimeValue._ztDepth;
                                            this._secondState.SetAlarm(true);
                                            description._secondState = (SecondState) this._secondState.Clone();
                                            state = true;
                                            analyseResult.result = state;
                                            analyseResult.percent = percent;
                                            analyseResult.resetAllParams = resetAllParams;
                                            analyseResult.md = description;
                                            return analyseResult;
                                        }
                                    }
                                }
                                break;
                            case TT_Down:
                                //下降趋势
                                if (this._listTimeValues.size() >= 1) {
                                    if (listDownSecValues.size() > 0) {
                                        int last = listDownSecValues.size() - 1;
                                        SecValue sv = listDownSecValues.get(last);
                                        percent = sv._sec / this._continuedTime;
                                        if (sv._value * -1.0 > this._totalNum && stepCompareUpDownValue * -1.0 > this._totalNum && sv._sec > this._continuedTime) {
                                            description._name = this._name;
                                            description._dtStart = tvStep._dateTime;
                                            description._dtEnd = sv._endTime;
                                            description._startValue = tvStep._value;
                                            description._endValue = currentTimeValue._value;
                                            description._startDepth = tvStep._depth;
                                            description._startZtDepth = tvStep._ztDepth;
                                            description._endDepth = currentTimeValue._depth;
                                            description._endZtDepth = currentTimeValue._ztDepth;

                                            if(this._trendTypeParam == TrendTypeParam.TT_TOTALNUM){
                                                //按总量
                                                description.lx = "符合下降异常趋势(总量:" + decimalFormat.format(this._totalNum) + idInfo + " ,当前值: " + valueDf.format(currentTimeValue._value)+idInfo+").";
                                            }else{
                                                //按倍数
                                                description.lx = "符合下降异常趋势(倍数:" + decimalFormat.format(this._mul) + "倍, 当前值:"+ valueDf.format(currentTimeValue._value)+").";
                                            }

                                            this._secondState.SetAlarm(true);
                                            description._secondState = (SecondState) this._secondState.Clone();
                                            analyseResult.result = true;
                                            analyseResult.percent = percent;
                                            analyseResult.resetAllParams = resetAllParams;
                                            analyseResult.md = description;
                                            return analyseResult;
                                        }
                                    }
                                }
                                break;
                        }
                        break;
                    default:
                        //波动趋势分析--（目前是按照连续波动才预警）
                        if (analyseType == AnalyseType.AT_BdRange) {
                            if (this._listTimeValues.size() < 2) {
                                analyseResult.result = false;
                                analyseResult.percent = percent;
                                return analyseResult;
                            }

                            boolean bInRange = true;
                            TimeValue tvFirst = this._listTimeValues.get(0);
                            int i = 0;
                            //this.SpanTimeSec() > 0 &&
                            double cmpValue = 0;
                            while (i < this._listTimeValues.size()) {
                                TimeValue tv3 = this._listTimeValues.get(i);
                                cmpValue = tv3._value - tvFirst._value;
                                if (Math.abs(cmpValue) > this._bdLtValue) {
                                    bInRange = false;
                                    break;
                                }
                                i++;
                            }
                            state = bInRange;
                            if(state){
                                tvStep = _listTimeValues.get(_listTimeValues.size()-1);
                                this._secondState.BdRange(tvFirst._dateTime, tvStep._dateTime,this._bdLtValue);
                                description._name = this._name;
                                description._dtStart = tvFirst._dateTime;
                                description._dtEnd = tvStep._dateTime;
                                description._startValue = tvFirst._value;
                                description._endValue = tvStep._value;
                                description._startDepth = tvStep._depth;
                                description._startZtDepth = tvStep._ztDepth;
                                description.lx = "超出波动范围" + "(小于"+ decimalFormat.format(this._bdLtValue) + idInfo +") ,当前波动"+ valueDf.format(cmpValue) + idInfo;

                                description._endDepth = tvStep._depth;
                                description._endZtDepth = tvStep._ztDepth;
                                this._secondState.SetAlarm(true);
                                description._secondState = (SecondState) this._secondState.Clone();
                                analyseResult.percent = percent;
                                analyseResult.resetAllParams = resetAllParams;
                                analyseResult.md = description;
                            }
                            if (!bInRange) {
                                this.ResetMonitorParams();
                            }

                            analyseResult.result = state;
                            analyseResult.percent = percent;

                            return analyseResult;
                        }
                        break;
                }
                state = false;
            }
        }
        analyseResult.result = state;
        analyseResult.percent = percent;
        return analyseResult;
    }

    public ArrayList<SecValue> UpdateLastSecValues(ArrayList<SecValue> listSecValues, SecValue sv) {
        if (listSecValues.size() == 0) {
            listSecValues.add(sv);
        } else {
            int last = listSecValues.size() - 1;
            if (listSecValues.get(last)._startTime == sv._startTime) {
                listSecValues.set(last, sv);
            } else {
                listSecValues.add(sv);
            }
        }

        return  listSecValues;
    }

    /**
     * 时间跨度（按秒计算）
     * @return
     */
    public int SpanTimeSec() {
        int sec = 0;
        if (this._listTimeValues.size() > 0) {
            sec = (int) (this._listTimeValues.get(this._listTimeValues.size() - 1)._dateTime.getTime()
                    - this._listTimeValues.get(0)._dateTime.getTime()) / 1000;
        }
        return sec;
    }

    /**
     * 根据检测时间调控数据
     */
    public void AdjustDataByMonitorTime() {
        Date dtNewestTime = this.NewestTime();
        if (null != dtNewestTime) {
            Date dtClear = DateUtils.addSeconds(dtNewestTime, (int) (-1.0 * this._monitorTime));
            for (int i = 0; i < this._listTimeValues.size(); i++) {
                if (!(this._listTimeValues.get(i)._dateTime.getTime() < dtClear.getTime())) {
                    break;
                }

                this._listTimeValues.remove(i);
                i--;
            }
            this._listMonitorRangeAngles.clear();
        }
    }

    public Date NewestTime() {
        if (this._listTimeValues != null && this._listTimeValues.size() > 0) {
            int lastIndex = this._listTimeValues.size() - 1;
            return this._listTimeValues.get(lastIndex)._dateTime;
        }
        return null;
    }
}
