import sys
import numpy as np
import pandas as pd
import string
import os
from pandas import Series
from matplotlib import pyplot as plt
from pandas.core.frame import DataFrame
from pandas.core.indexes.base import Index
from LIB.BACKEND import DBManager
import datetime
import time
import string
import re



class SamplingSafty:
    def __init__(self):
        pass
    def main(sn,param,bms_info,df_Diag_Ram_in):
        df_Diag_Ram_Update_inside=DataFrame(columns=['start_time', 'end_time', 'product_id', 'code', 'level', 'info','advice'])
        df_Diag_Ram_Update_inside=df_Diag_Ram_Update_inside.append(df_Diag_Ram_in)
        global QuitErrCount 
        VolStarkCount=[0 for i in range(param.CellVoltNums)]
        VolCount=0
        QuitErrCount=[0 for i in range(param.FaultCount)]

        #--------------该电池的所有当前故障-------------



        for i in range(0,len(bms_info)):
            if i==0:
                bms_infoP=bms_info.loc[i]
            elif len(bms_info)>=1:
                    bms_infoP=bms_info.loc[i-1]
            df_Diag_Ram_Update_inside,VolStarkCount,VolCount=SamplingSafty.VoltSamplingDiag(sn,bms_info.loc[i],bms_infoP,param,VolStarkCount,VolCount,df_Diag_Ram_Update_inside)   
            df_Diag_Ram_Update_inside=SamplingSafty.TempSamplingDiag(sn,bms_info.loc[i],bms_infoP,param,df_Diag_Ram_Update_inside)
                # FltInfo=SamplingSafty.CrntSamplingDiag(sn,bms_info.loc[i],FltInfo,param)
        return df_Diag_Ram_Update_inside



    def VoltSamplingDiag(sn,bms_infoN,bms_infoP,param,VolStarkCount,VolCount,df_Diag_Ram):
        InVMaxBatNo=[]
        InVMinBatNo=[]
        StackVolNo=[]
        OutlierVolNo=[]
        ErrorFlg=0
        #——————————————————————取最高最低电压————————————————————————————————

        VoltageNum=['单体电压'+str(i) for i in range(1,param.CellVoltNums+1)]
        CellVoltage=bms_infoN[VoltageNum]/1000
        CellVoltageP=bms_infoP[VoltageNum]/1000
        MaxVolt=CellVoltage.max()
        MinVolt=CellVoltage.min()
        MaxVoltNum=CellVoltage[MaxVolt==CellVoltage].index
        MinVoltNum=CellVoltage[MinVolt==CellVoltage].index
        InVMaxBatNo=CellVoltage[CellVoltage>=param.CellOVlmt].index
        InVMinBatNo=CellVoltage[CellVoltage<=param.CellUVlmt].index
        if param.CellVoltNums>2:
            AvgVol=(CellVoltage.sum()-MaxVolt-MinVolt)/(param.CellVoltNums-2)
        else:
            AvgVol=CellVoltage.mean()
        #—————————————————————————————电压无效和断线判断———————————————————————
        if len(InVMaxBatNo):
            if len(InVMinBatNo):
                QuitErrCount[10]=0
                if not 'C310' in df_Diag_Ram['code'].values.tolist():#如果故障发生当前故障中没有该故障，则压入该故障
                    df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,'C310',3,'电池电压采样断线,最高电压为{:.2f}V,电池编号为{}，最低电压为{:.2f}V,电池编号为{}'.format(MaxVolt,InVMaxBatNo.values,MinVolt,InVMinBatNo.values),'返厂维修']
                    ErrorFlg=1  
                else:#如果故障发生当前故障中有该故障，则不进行操作
                    pass                 
            else:#如果没有故障，并且当前故障表中有该故障，则判断故障是否结束
                QuitErrCount[50]=0
                if 'C310' in df_Diag_Ram['code'].values.tolist():
                    QuitErrCount[10]=QuitErrCount[10]+1
                    if QuitErrCount[10]>3:
                        QuitErrCount[10]=4
                        end_time=datetime.datetime.now()
                        end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
                        df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']=='C310'].index,['end_time']]=end_time
                    else:
                        pass
                else:
                    pass
                if not 'C350' in df_Diag_Ram['code'].values.tolist():
                    df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,'C350',3,str(InVMaxBatNo.values)+'号电压大于{:.2f}V,采样无效'.format(param.CellOVlmt),'返厂维修']
                    ErrorFlg=1
                else:
                    pass
        elif len(InVMinBatNo):
            QuitErrCount[50]=0
            if not 'C350' in df_Diag_Ram['code'].values.tolist():
                df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,'C350',3,str(InVMinBatNo.values)+'号电压小于{:.2f}V,采样无效'.format(param.CellUVlmt),'返厂维修']
                ErrorFlg=1
            else:
                pass
        else:
            if 'C350' in df_Diag_Ram['code'].values.tolist():
                QuitErrCount[50]=QuitErrCount[50]+1
                if QuitErrCount[50]>3:
                    QuitErrCount[50]=4
                    end_time=datetime.datetime.now()
                    end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
                    df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']==50].index,['end_time']]=end_time                   
                else:
                    pass
            else:
                pass                                      
       #——————————————————————————————————电压卡滞和离群判断—————————————————————————
        if ErrorFlg==0:
            AvgVolGap=CellVoltage-AvgVol
            OutlierVolNo=AvgVolGap[AvgVolGap>=param.AvgVolGap].index
            if len(OutlierVolNo) and abs(bms_infoN['总电流[A]'])<2 and not 'C251' in df_Diag_Ram['code']:
                VolCount=VolCount+1
                QuitErrCount[51]=0
                if VolCount>10:
                    VolCount=11
                    if not 'C251' in df_Diag_Ram['code'].values.tolist():#如果故障发生当前故障中没有该故障，则压入该故障
                        df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,'C251',2,str(OutlierVolNo.values)+'号电池电压离群','技术介入诊断']
                        ErrorFlg=1            
                    else:#如果故障发生当前故障中有该故障，则不进行操作
                        pass                
            else:
                VolCount=0
                if 'C251' in df_Diag_Ram['code'].values.tolist():
                    QuitErrCount[51]=QuitErrCount[51]+1
                    if QuitErrCount[51]>3:
                        QuitErrCount[51]=4
                        end_time=datetime.datetime.now()
                        end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
                        df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']=='C251'].index,['end_time']]=end_time                
                    else:
                        pass
                else:
                    pass
            # -------------------卡滞逻辑未加-------------------------------------
            # if (abs(float(bms_infoN['总电流[A]']))>=10 and not 'PK504' in sn) or (abs(float(bms_infoN['总电流[A]']))>=15 and 'PK504' in sn):
            #     StackVolNo=CellVoltage[abs(CellVoltage-CellVoltageP)<=0.0001].index
            #     NotStackVolNo=CellVoltage[abs(CellVoltage-CellVoltageP)>0.0001].index
            #     if len(StackVolNo) and not 52 in df_Diag_Ram['code']:
            #         StackVolNo=[int(s) for s in StackVolNo.str.replace(r'[^0-9]','').tolist()]
            #         NotStackVolNo=[int(s) for s in NotStackVolNo.str.replace(r'[^0-9]','').tolist()]
            #         for i in StackVolNo:
            #             VolStarkCount[i-1]=VolStarkCount[i-1]+1
            #         for i in NotStackVolNo:
            #             VolStarkCount[i-1]=0
            #     if [s for s in VolStarkCount]>10:
            #         StacVolNo=

        return df_Diag_Ram,VolStarkCount,VolCount

    def TempSamplingDiag(sn,bms_infoN,bms_infoP,param,df_Diag_Ram):
        InVMaxBatNo=[]
        InVMinBatNo=[]
        StackVolNo=[]
        OutlierVolNo=[]
        ErrorFlg=0
        #——————————————————————Cell取最高最低温度————————————————————————————————
        TempNum=['单体温度'+str(i) for i in range(1,param.CellTempNums+1)]
        CellTemp=bms_infoN[TempNum]
        CellTempP=bms_infoP[TempNum]
        maxCellTemp=CellTemp.max()
        minCellTemp=CellTemp.min()
        MaxVoltNum=CellTemp[maxCellTemp==CellTemp].index
        MinVoltNum=CellTemp[minCellTemp==CellTemp].index
        InVMaxTempBatNo=CellTemp[CellTemp>=param.PackOTlmt].index
        InVMinTempBatNo=CellTemp[CellTemp<=param.PackUTlmt].index
        if param.CellTempNums>2:
            AvgCellTemp=(CellTemp.sum()-maxCellTemp-minCellTemp)/(param.CellTempNums-2)
        else:
            AvgCellTemp=CellTemp.mean()        
        #——————————————————————温度无效，离群和断线判断———————————————————————
        if len(InVMaxTempBatNo):
            if len(InVMinTempBatNo):
                QuitErrCount[53]=0
                if not 'C353' in df_Diag_Ram['code'].values.tolist():#如果故障发生当前故障中没有该故障，则压入该故障
                    df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,'C353',3,'电池温度采样断线,最高温度为{}℃,电池编号为{}，最低温度为{}℃,电池编号为{}'.format(maxCellTemp,InVMaxTempBatNo.values,minCellTemp,InVMinTempBatNo.values),'返厂维修']
                    ErrorFlg=1 
                else:#如果故障发生当前故障中有该故障，则不进行操作
                    pass                 
            else:#如果没有故障，并且当前故障表中有该故障，则判断故障是否结束
                QuitErrCount[2]=0
                if 'C353' in df_Diag_Ram['code'].values.tolist():
                    QuitErrCount[53]=QuitErrCount[53]+1
                    if QuitErrCount[53]>3:
                        QuitErrCount[53]=4
                        end_time=datetime.datetime.now()
                        end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
                        df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']=='C353'].index,['end_time']]=end_time
                    else:
                        pass
                else:
                    pass
                if not 'C302' in df_Diag_Ram['code'].values.tolist():
                    df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,'C302',3,str(InVMaxTempBatNo.values)+'号温度大于{}℃,采样无效'.format(param.PackOTlmt),'联系用户核实电池温度情况，并返厂维修']
                    ErrorFlg=1
                else:
                    pass
        elif len(InVMinTempBatNo):
            QuitErrCount[2]=0
            if not 'C302' in df_Diag_Ram['code'].values.tolist():
                df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,'C302',3,str(InVMinTempBatNo.values)+'号温度小于{}℃,采样无效'.format(param.PackUTlmt),'返厂维修']
                ErrorFlg=1
            else:
                pass
        else:
            if 'C302' in df_Diag_Ram['code'].values.tolist():
                QuitErrCount[2]=QuitErrCount[2]+1
                if QuitErrCount[2]>3:
                    QuitErrCount[2]=4
                    end_time=datetime.datetime.now()
                    end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
                    df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']=='C302'].index,['end_time']]=end_time                   
                else:
                    pass
            else:
                pass             
        if ErrorFlg==0:
            AvgCellTempGap=abs(CellTemp-AvgCellTemp)
            OutlierTempNo=AvgCellTempGap[AvgCellTempGap>=param.AvgCellTempGap].index
            if len(OutlierTempNo):
                QuitErrCount[8]=0
                if not 'C108' in df_Diag_Ram['code'].values.tolist():#如果故障发生当前故障中没有该故障，则压入该故障
                    df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,'C108',1,str(OutlierTempNo.values)+'号电池异常温度离群','技术介入诊断']
                    ErrorFlg=1            
                else:#如果故障发生当前故障中有该故障，则不进行操作
                    pass
            else:
                if 'C108' in df_Diag_Ram['code'].values.tolist():
                    QuitErrCount[8]=QuitErrCount[8]+1
                    if QuitErrCount[8]>3:
                        QuitErrCount[8]=4
                        end_time=datetime.datetime.now()
                        end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
                        df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']=='C108'].index,['end_time']]=end_time
                    else:
                        pass
                else:
                    pass
        #——————————————————————————————————OtherTemp————————————————————————————————————
        if param.OtherTempNums>0:
            OtherTempNum=['其他温度'+str(i) for i in range(1,param.OtherTempNums+1)] 
            OtherTemp=bms_infoN[OtherTempNum]
            if 'MGMLX' in sn:
                OtherTemp['其他温度2']=OtherTemp['其他温度1']
            else:
                pass
            OtherTemppP=bms_infoP[OtherTempNum]
            maxOtherTemp=OtherTemp.max()
            minOtherTemp=OtherTemp.min()
            MaxVoltNum=OtherTemp[maxOtherTemp==OtherTemp].index
            MinVoltNum=OtherTemp[minOtherTemp==OtherTemp].index
            InVMaxOtherTempBatNo=OtherTemp[OtherTemp>=param.OtherOTlmt].index
            InVMinOtherTempBatNo=OtherTemp[OtherTemp<=param.OtherUTlmt].index
            if param.OtherTempNums>2:
                AvgOtherTemp=(OtherTemp.sum()-maxOtherTemp-minOtherTemp)/(param.OtherTempNums-2)
            else:
                AvgOtherTemp=OtherTemp.mean()        
            #——————————————————————温度无效，离群和断线判断———————————————————————
            if len(InVMaxOtherTempBatNo):
                if len(InVMinOtherTempBatNo):
                    QuitErrCount[54]=0
                    if not 'C354' in df_Diag_Ram['code'].values.tolist():#如果故障发生当前故障中没有该故障，则压入该故障
                        df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,'C354',3,'其他温度采样断线,最高温度为{}℃,传感器编号为{}，最低温度为{}℃,传感器编号为{}'.format(maxOtherTemp,InVMaxOtherTempBatNo.values,minOtherTemp,InVMinOtherTempBatNo.values),'返厂维修']
                        ErrorFlg=1 
                    else:#如果故障发生当前故障中有该故障，则不进行操作
                        pass                 
                else:#如果没有故障，并且当前故障表中有该故障，则判断故障是否结束
                    QuitErrCount[55]=0
                    if 'C354' in df_Diag_Ram['code'].values.tolist():
                        QuitErrCount[54]=QuitErrCount[54]+1
                        if QuitErrCount[54]>3:
                            QuitErrCount[54]=4
                            end_time=datetime.datetime.now()
                            end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
                            df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']=='C354'].index,['end_time']]=end_time
                        else:
                            pass
                    else:
                        pass
                    if not 'C355' in df_Diag_Ram['code'].values.tolist():
                        df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,'C355',3,'传感器温度大于{}℃,采样无效'.format(param.OtherOTlmt),'联系用户核实电池温度情况，并返厂维修']
                        ErrorFlg=1
                    else:
                        pass
            elif len(InVMinTempBatNo):
                QuitErrCount[55]=0
                if not 'C355' in df_Diag_Ram['code'].values.tolist():
                    df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,'C355',3,'传感器温度小于{}℃,采样无效'.format(param.OtherUTlmt),'返厂维修']
                    ErrorFlg=1
                else:
                    pass
            else:
                if 'C355' in df_Diag_Ram['code'].values.tolist():
                    QuitErrCount[55]=QuitErrCount[55]+1
                    if QuitErrCount[55]>3:
                        QuitErrCount[55]=4
                        end_time=datetime.datetime.now()
                        end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
                        df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']=='C355'].index,['end_time']]=end_time                   
                    else:
                        pass
                else:
                    pass             
            if ErrorFlg==0:
                AvgOtherTempGap=abs(OtherTemp-AvgOtherTemp)
                OutlierOtherTempNo=AvgOtherTempGap[AvgOtherTempGap>=param.AvgOtherTempGap].index
                if len(OutlierOtherTempNo):
                    QuitErrCount[56]=0
                    if not 'C156' in df_Diag_Ram['code'].values.tolist():#如果故障发生当前故障中没有该故障，则压入该故障
                        df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,'C156',1,'传感器温度异常离群','技术介入诊断']
                        ErrorFlg=1            
                    else:#如果故障发生当前故障中有该故障，则不进行操作
                        pass
                else:
                    if 'C156' in df_Diag_Ram['code'].values.tolist():
                        QuitErrCount[56]=QuitErrCount[56]+1
                        if QuitErrCount[56]>3:
                            QuitErrCount[56]=4
                            end_time=datetime.datetime.now()
                            end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
                            df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']=='C156'].index,['end_time']]=end_time
                        else:
                            pass
                    else:
                        pass

                if (maxOtherTemp-maxCellTemp)>param.AvgOtherTempGap and  maxOtherTemp<param.OtherOTlmt and maxCellTemp<param.PackOTlmt:
                    QuitErrCount[56]=0
                    if not 'C156' in df_Diag_Ram['code'].values.tolist():
                        df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,'C156',1,'传感器温度异常离群','技术立即介入诊断']
                        ErrorFlg=1
                else:
                    if 'C156' in df_Diag_Ram['code'].values.tolist():
                            QuitErrCount[56]=QuitErrCount[56]+1
                            if QuitErrCount[56]>3:
                                QuitErrCount[56]=4
                                end_time=datetime.datetime.now()
                                end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
                                df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']=='C156'].index,['end_time']]=end_time
                                
                if (maxCellTemp-maxOtherTemp)>param.AvgOtherTempGap and  maxOtherTemp<param.OtherOTlmt and maxCellTemp<param.PackOTlmt and not 8 in df_Diag_Ram['code']:
                    QuitErrCount[8]=0
                    if not 'C108' in df_Diag_Ram['code'].values.tolist():
                        df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,'C108',1,str(OutlierTempNo.values)+'号电芯温度异常离群','技术立即介入诊断']
                        
                        ErrorFlg=1
                else:
                    if 'C108' in df_Diag_Ram['code'].values.tolist():
                            QuitErrCount[8]=QuitErrCount[8]+1
                            if QuitErrCount[8]>3:
                                QuitErrCount[8]=4
                                end_time=datetime.datetime.now()
                                end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
                                df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']=='C108'].index,['end_time']]=end_time              

        return df_Diag_Ram