import pandas as pd
import numpy as np
from LIB.BACKEND.DataPreProcess import DataPreProcess
import os
import math
import datetime
import time

def cal_mileage(sn,data_gps,data_bms):

    
    #将时间戳由 "%Y-%m-%d %H:%M:%S" 切换为 sec
    def timeconvert(df_in,column_name):  
        df=df_in.copy()
        df.index=range(len(df))
        time=df[column_name]
        timeInSeries=[]
        
        time2=datetime.datetime.strptime(time[0],"%Y-%m-%d %H:%M:%S")
        for k in range(len(time)):
            time1=datetime.datetime.strptime(time[k],"%Y-%m-%d %H:%M:%S")    
            t=(time1-time2)
            timeInSeries.append(t.days*86400+t.seconds)
        df.loc[:,'相对时间[s]']=pd.DataFrame(timeInSeries,columns=['相对时间[s]'])
        return df

    data_bms=timeconvert(data_bms,'时间戳')

    #计算累积能量
    def cal_accumKwh(df_in):
        I=df_in['总电流[A]'].values
        V=df_in['总电压[V]'].values
        t=df_in['相对时间[s]'].values
        accumAh=[0.0]
        for k in range(1,len(I)):
            accumAh_temp=(t[k]-t[k-1])*((I[k]+I[k-1])/(2*3600))*(V[k]+V[k-1])/2/1000
            accumAh.append(accumAh[-1]+accumAh_temp)
        df_in.loc[:,'累积能量[Kwh]']=accumAh
        return(df_in)

    data_bms=cal_accumKwh(data_bms)

    #合并两张表格
    df_bms=data_bms.copy()
    df_gps=data_gps.copy()
    df_bms.set_index(["时间戳"], inplace=True)
    df_gps.set_index(["时间戳"], inplace=True)
    df_temp = df_bms.append(df_gps)
    df_temp=df_temp.sort_index(ascending=True)
    df_temp.loc[:,'时间']=df_temp.index
    df_temp.index=[k for k in range(len(df_temp))]
    df_sheetCat=df_temp.copy()
    df_sheetCat=timeconvert(df_sheetCat,'时间')
    df_sheetCat=df_sheetCat.rename(columns={'时间':'时间戳'})
    df_sheetCat=DataPreProcess.data_split_by_status(DataPreProcess,df_sheetCat, drive_interval_threshold=120, charge_interval_threshold=300, drive_stand_threshold=120, charge_stand_threshold=300)

    #数据整理
    df1=df_sheetCat.copy()
    #如果前后data_status均不为none,但是本次为none,则将本次data_status设置为与上次相同。
    data_status=df1['data_status'].values
    for k in range(1,len(data_status)-1):
        if data_status[k-1]!='none' and data_status[k+1]!='none':
            df1.loc[k,'data_status']=data_status[k-1]

    #如果前后两次电流值均不为nan,则将总电流[A]、总电压[V]、SOC[%]设置为与前次相同。
    data_current=df1['总电流[A]'].values
    for k in range(1,len(data_current)-1):
        if not math.isnan(data_current[k-1]) and not math.isnan(data_current[k+1]) and math.isnan(data_current[k]):
            df1.loc[k,'总电流[A]']=df1.loc[k-1,'总电流[A]']
            df1.loc[k,'总电压[V]']=df1.loc[k-1,'总电压[V]']
            df1.loc[k,'SOC[%]']=df1.loc[k-1,'SOC[%]']

    #如果前后两次能量均不是NAN，但是本次为NAN，则将上次的能量指赋值给本次
    AccumEnergy=df1['累积能量[Kwh]'].values
    for k in range(1,len(AccumEnergy)-1):
        if not math.isnan(AccumEnergy[k-1]) and not math.isnan(AccumEnergy[k+1]) and math.isnan(AccumEnergy[k]):
            df1.loc[k,'累积能量[Kwh]']=AccumEnergy[k-1]

    #删除一些无用列，获取用于计算的数据
    df_input=df1[['时间戳','总电流[A]', '总电压[V]','SOC[%]','相对时间[s]', '累积能量[Kwh]','纬度', '经度','data_status']]
    #筛选出有经纬度信息的数据
    df_gpsOnly=df_input[df_input['纬度']>0]

    #根据经纬度获取两点之间的距离
    def cal_dis_meters(radius,latitude1, longitude1,latitude2, longitude2):  
        radLat1 = (math.pi/180)*latitude1  
        radLat2 = (math.pi/180)*latitude2  
        radLng1 = (math.pi/180)*longitude1  
        radLng2= (math.pi/180)*longitude2      
        d=2*math.asin(math.sqrt(math.pow(math.sin((radLat1-radLat2)/2.0),2)+math.cos(radLat1)*math.cos(radLat2)*math.pow(math.sin((radLng1-radLng2)/2.0),2)))*radius
        return d

    #根据gps数据计算△距离1和△距离2
    #△距离1:直接根据两次的经度和纬度计算得到的马氏距离
    #△距离2：当两次上报经纬度的时间间隔＜60sec时，如果车辆为行驶状态则使用两次的经纬度求得的马氏距离，
    #如果车辆不为行驶状态，则为0.
    index_list=df_gpsOnly.index
    pos_list=df_gpsOnly[['纬度','经度']].values
    time_list=df_input['相对时间[s]'].values
    Energy_list=df_input['累积能量[Kwh]'].values
    for k in range(1,len(pos_list)):
        latitude1=pos_list[k-1][0]
        longitude1=pos_list[k-1][1]
        latitude2=pos_list[k][0]
        longitude2=pos_list[k][1]
        dlt_odo=cal_dis_meters(6378.137,latitude1, longitude1,latitude2, longitude2)
        df_gpsOnly.loc[index_list[k],'△距离1']=dlt_odo    
        if time_list[index_list[k]]-time_list[index_list[k-1]]<60:#两次上传GPS数据时间间隔小于60sec
            if df_gpsOnly.loc[index_list[k],'data_status']=='drive' :   
                df_gpsOnly.loc[index_list[k],'△距离2']=dlt_odo
            elif df_gpsOnly.loc[index_list[k],'data_status']=='none' :
                df_gpsOnly.loc[index_list[k],'△距离2']=dlt_odo
            else:
                df_gpsOnly.loc[index_list[k],'△距离2']=0

    #如果某一段数据中有gps数据但是没有bms数据，里程按照gps数据计算，但是到有gps数据之后，发现累积能量变化不大于0，因此需要将这期间的里程均设置为0km            
    df_gpsOnly_copy=df_gpsOnly.copy()
    df_gpsOnly_copy.index=[i for i in range(len(df_gpsOnly))]
    df_bmsOnly=df_gpsOnly_copy[df_gpsOnly_copy['总电压[V]']>0]
    energy2=df_bmsOnly['累积能量[Kwh]'].values
    df_bmsOnly_index=df_bmsOnly.index.values
    for k in range(1,len(df_bmsOnly)):
        if not (energy2[k]-energy2[k-1]>0):
            for n in range(df_bmsOnly_index[k-1],df_bmsOnly_index[k]+1):
                df_gpsOnly_copy.loc[n,'△距离2']=0

    dis2=df_gpsOnly_copy['△距离2'].values
    relatedTime=df_gpsOnly_copy['相对时间[s]'].values
    nan_flag=0

    for k in range(1,len(dis2)):
        if math.isnan(dis2[k]) and (not math.isnan(dis2[k-1])): #本次△距离2为NAN但是上次不为NAN
            nan_flag=1
            ###平均能耗计算
            st_time=relatedTime[k]-600  #10min之前的时刻点
            df2=df_gpsOnly_copy[df_gpsOnly_copy['相对时间[s]']>=st_time]
            df_temp2=df2[df2['相对时间[s]']<=relatedTime[k]]
            df_temp2=df_temp2[['相对时间[s]','累积能量[Kwh]','△距离2']]
            df_temp3=df_temp2.dropna(axis=0,how='any') 
            if len(df_temp3)>5:
                # st_time=relatedTime[k-1]-600  #10min之前的时刻点
                # df2=df_gpsOnly_copy[df_gpsOnly_copy['相对时间[s]']>=st_time]
                # df_temp2=df2[df2['相对时间[s]']<=relatedTime[k]]
                
                energy=df_temp3['累积能量[Kwh]'].values
                dis_temp=df_temp3['△距离2'].values
                # dis_temp_delet_nan=dis_temp[np.logical_not(np.isnan(dis_temp))]
                df_gpsOnly_copy.loc[k,'△能量[Kwh]']=energy[-1]-energy[0]
                df_gpsOnly_copy.loc[k,'累积距离[km]']=dis_temp[1:-1].sum()
                if energy[-1]-energy[0]>0:
                    df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=min(max(df_gpsOnly_copy.loc[k,'累积距离[km]']/df_gpsOnly_copy.loc[k,'△能量[Kwh]'],25),50)
                else:
                    if dis_temp[1:-1].sum()>0:
                        df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=30
                    else:
                        df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=0
            else:
                df_temp2=df_gpsOnly_copy[df_gpsOnly_copy['相对时间[s]']<=relatedTime[k]]
                df_energyPerKm=df_gpsOnly_copy[df_gpsOnly_copy['能耗[km/kwh]']>0]
                df_energyPerKm.index=[i for i in range(len(df_energyPerKm))]
                total_num=len(df_energyPerKm)
                #统计最近10次的平均能耗，用于补充dis2前后都为nan时刻处的能耗及距离，
                ##如果不足10次按照实际次数统计
                if total_num>10:
                    energycost_acc=0
                    for i in range(10):
                        energycost_acc=energycost_acc+df_energyPerKm.loc[total_num-i-1,'能耗[km/kwh]']
                    avg_energyCost=min(max(energycost_acc/10,25),50)
                    df_gpsOnly_copy.loc[k,'△能量[Kwh]']=1
                    df_gpsOnly_copy.loc[k,'累积距离[km]']=avg_energyCost
                    df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=avg_energyCost
                elif total_num>0:
                    avg_energyCost=min(max(df_energyPerKm['能耗[km/kwh]'].values.mean(),25),50)
                    df_gpsOnly_copy.loc[k,'△能量[Kwh]']=1
                    df_gpsOnly_copy.loc[k,'累积距离[km]']=avg_energyCost
                    df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=avg_energyCost
                else:
                    df_gpsOnly_copy.loc[k,'△能量[Kwh]']=df_gpsOnly_copy.loc[k-1,'△能量[Kwh]'] 
                    df_gpsOnly_copy.loc[k,'累积距离[km]']=df_gpsOnly_copy.loc[k-1,'累积距离[km]']
                    df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=df_gpsOnly_copy.loc[k-1,'能耗[km/kwh]']
                
            
            ####行驶里程估计
            energy1=df_temp2['累积能量[Kwh]'].values
            if energy1[-1]-energy1[-2]>0:
                gps_dis=df_gpsOnly_copy.loc[k,'△距离1']
                delta_t=df_gpsOnly_copy.loc[k,'相对时间[s]']-df_gpsOnly_copy.loc[k-1,'相对时间[s]']
                vehspd=gps_dis*3600/delta_t
                if vehspd>30:
                    df_gpsOnly_copy.loc[k,'△距离3[km]']=(energy1[-1]-energy1[-2])*df_gpsOnly_copy.loc[k,'能耗[km/kwh]']
                else:
                    df_gpsOnly_copy.loc[k,'△距离3[km]']=max((energy1[-1]-energy1[-2])*df_gpsOnly_copy.loc[k,'能耗[km/kwh]'],gps_dis)
            else:
                df_gpsOnly_copy.loc[k,'△距离3[km]']=0

            df_gpsOnly_copy.loc[k,'△距离2']=df_gpsOnly_copy.loc[k,'△距离3[km]']
            
        elif math.isnan(dis2[k]) and (math.isnan(dis2[k-1])) and nan_flag==1: #本次△距离为NAN上次也为NAN
            df_energyPerKm=df_gpsOnly_copy[df_gpsOnly_copy['能耗[km/kwh]']>0]
            df_energyPerKm.index=[i for i in range(len(df_energyPerKm))]
            total_num=len(df_energyPerKm)
            #统计最近10次的平均能耗，用于补充dis2前后都为nan时刻处的能耗及距离，
            ##如果不足10次按照实际次数统计
            if total_num>10:
                energycost_acc=0
                for i in range(10):
                    energycost_acc=energycost_acc+df_energyPerKm.loc[total_num-i-1,'能耗[km/kwh]']
                avg_energyCost=min(max(energycost_acc/10,25),50)
                df_gpsOnly_copy.loc[k,'△能量[Kwh]']=1
                df_gpsOnly_copy.loc[k,'累积距离[km]']=avg_energyCost
                df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=avg_energyCost
            elif total_num>0:
                avg_energyCost=min(max(df_energyPerKm['能耗[km/kwh]'].values.mean(),25),50)
                df_gpsOnly_copy.loc[k,'△能量[Kwh]']=1
                df_gpsOnly_copy.loc[k,'累积距离[km]']=avg_energyCost
                df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=avg_energyCost
            else:
                df_gpsOnly_copy.loc[k,'△能量[Kwh]']=df_gpsOnly_copy.loc[k-1,'△能量[Kwh]'] 
                df_gpsOnly_copy.loc[k,'累积距离[km]']=df_gpsOnly_copy.loc[k-1,'累积距离[km]']
                df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=df_gpsOnly_copy.loc[k-1,'能耗[km/kwh]']
            
            ##计算行驶里程
            delta_energy=df_gpsOnly_copy.loc[k,'累积能量[Kwh]']-df_gpsOnly_copy.loc[k-1,'累积能量[Kwh]']
            if delta_energy>0:
                gps_dis=df_gpsOnly_copy.loc[k,'△距离1']
                delta_t=df_gpsOnly_copy.loc[k,'相对时间[s]']-df_gpsOnly_copy.loc[k-1,'相对时间[s]']
                vehspd=gps_dis*3600/delta_t
                if vehspd>30:
                    df_gpsOnly_copy.loc[k,'△距离3[km]']=delta_energy*df_gpsOnly_copy.loc[k,'累积距离[km]']/df_gpsOnly_copy.loc[k,'△能量[Kwh]']
                else:
                    df_gpsOnly_copy.loc[k,'△距离3[km]']=max(delta_energy*df_gpsOnly_copy.loc[k,'累积距离[km]']/df_gpsOnly_copy.loc[k,'△能量[Kwh]'],gps_dis)
            else:
                df_gpsOnly_copy.loc[k,'△距离3[km]']=0
            
            df_gpsOnly_copy.loc[k,'△距离2']=df_gpsOnly_copy.loc[k,'△距离3[km]']
        else:
            df_gpsOnly_copy.loc[k,'△能量[Kwh]']=1
            df_gpsOnly_copy.loc[k,'累积距离[km]']=25
            df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=25
            df_gpsOnly_copy.loc[k,'△距离3[km]']=df_gpsOnly_copy.loc[k,'△距离2']

    ###############输出计算结果##################
    ############################################
    df_gpsOnly_copy.loc[0,'累积里程[km]']=0
    df_gpsOnly_copy.loc[0,'日期']=str(df_gpsOnly_copy.loc[0,'时间戳'])[0:10]  

    for k in range(1,len(df_gpsOnly_copy)):
        df_dis_temp=df_gpsOnly_copy['△距离3[km]'].values[0:k+1]
        df_dis_temp1=df_dis_temp[np.logical_not(np.isnan(df_dis_temp))]
        if len(df_dis_temp1)>0:
            df_gpsOnly_copy.loc[k,'累积里程[km]']=df_dis_temp1.sum()
        else:
            df_gpsOnly_copy.loc[k,'累积里程[km]']=df_gpsOnly_copy.loc[k-1,'累积里程[km]']
        df_gpsOnly_copy.loc[k,'日期']=str(df_gpsOnly_copy.loc[k,'时间戳'])[0:10] 

    datetime1=np.unique(df_gpsOnly_copy['日期'].values)
    df_result=pd.DataFrame(index=datetime1)
    list_result=[]
    list_day_odo=[]

    for k in range(len(datetime1)):
        df_day=df_gpsOnly_copy[df_gpsOnly_copy['日期']==datetime1[k]]
        odo_day=df_day['累积里程[km]'].values
        df_result.loc[datetime1[k],'累积里程[km]']=odo_day[-1]-odo_day[0]
        df_day['累积里程[km]']=odo_day-odo_day[0]
        list_day_odo.extend(odo_day-odo_day[0])
        list_result.append([datetime1[k],df_day])

    df_gpsOnly_copy.loc[:,'每日累积里程[km]']=list_day_odo

    #删除一些无用列，获取用于计算的数据
    df_output=df_gpsOnly_copy[['时间戳','data_status','SOC[%]','每日累积里程[km]']]

    #添加sn
    df_output['sn'] = sn
    return df_output

