# -*- coding: utf-8 -*-
"""
Created on Sat Sep 25 23:26:27 2021

@author: admin
"""
import pandas as pd
import numpy as np
from LIB.BACKEND.DataPreProcess import DataPreProcess
import os
import math
import datetime
import time

#将时间戳由 "%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(str(time[0]),"%Y-%m-%d %H:%M:%S")
    for k in range(len(time)):
        time1=datetime.datetime.strptime(str(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

#计算累积能量
def cal_accumKwh(df_in):
    df_in1=df_in.copy()
    df1=df_in1[['总电流[A]','总电压[V]','相对时间[s]']]
    df1=df1.dropna(axis=0,how='any')
    I=df1['总电流[A]'].values
    V=df1['总电压[V]'].values
    t=df1['相对时间[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)
    df1.loc[:,'累积能量[Kwh]']=accumAh
    df_out=pd.merge(df_in1,df1[['累积能量[Kwh]']],how='left',left_index=True, right_index=True)
    return(df_out)

#将时间格式化为整数
def str_data_to_num(str_data):
    # 格式时间成毫秒
    strptime = time.strptime(str_data,"%Y-%m-%d %H:%M:%S")
    # print("strptime",strptime)
    mktime = int(time.mktime(strptime)*1000)
    # print("mktime",mktime)
    return mktime

def df_date_To_int(df_in):
    df=df_in.copy()
    for k in range(len(df)):
        df.loc[k,'绝对时间[ms]']=str_data_to_num(df['时间戳'][k])
    return df

#根据经纬度获取两点之间的距离
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

def cal_gps_distance(df_in):
    #根据gps数据计算△距离1和△距离2
    #△距离1:直接根据两次的经度和纬度计算得到的马氏距离
    #△距离2：当两次上报经纬度的时间间隔＜60sec时，如果车辆为行驶状态则使用两次的经纬度求得的马氏距离，
    #如果车辆不为行驶状态，则为0.
    df_gpsOnly=df_in[df_in['纬度']>0]
    index_list=df_gpsOnly.index
    pos_list=df_gpsOnly[['纬度','经度']].values
    time_list=df_in['相对时间[s]'].values
    # Energy_list=df_in['累积能量[Kwh]'].values
    df_gpsOnly.loc[index_list[0],'△距离1']=0
    df_gpsOnly.loc[index_list[0],'△距离2']=0
    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
    return(df_gpsOnly)


def real_odo(df_in,avg_cost):
    # df_handle=df_in.copy()
    df=timeconvert(df_in,"时间戳")#计算相对时间
    df=cal_accumKwh(df)#计算累积能量

    positive_lat_index=df[df['纬度']>0].index
    if len(positive_lat_index)>2:
        first_index=positive_lat_index[0]
        end_index=positive_lat_index[-1]
        #将数据分割为有第一个GPS数据之前（part1）、
        #有最后一个GPS数据之后(part3)以及
        #有第一个GPS数据和最后一个GPS数据中间的数据(part3)
        part1=df[0:first_index+1]
        part2=df[first_index:end_index+1]
        part3=df[end_index:-1]
        
        #第一部分距离计算    
        part1.index=[i for i in range(len(part1))]
        part1.loc[0,'△距离']=0
        AccumEnergy1=part1['累积能量[Kwh]'].values
        for k1 in range(1,len(part1)):
            if (AccumEnergy1[k1]-AccumEnergy1[k1-1])>0:
                part1.loc[k1,'△距离']=(AccumEnergy1[k1]-AccumEnergy1[k1-1])*avg_cost
                part1.loc[k1,'方法']=4
            else:
                part1.loc[k1,'△距离']=0
                part1.loc[k1,'方法']=5
        
        #第二部分计算
        part2_gps=part2[part2['纬度']>0]
        part2_gps.index=[i for i in range(len(part2_gps))]
        times_list=part2_gps['相对时间[s]'].values
        lat=part2_gps['纬度'].values
        lng=part2_gps['经度'].values
        AccumEnergy2=part2_gps['累积能量[Kwh]'].values
        part2_gps.loc[0,'△距离']=0
        for k2 in range(1,len(part2_gps)):
            delta_energy=AccumEnergy2[k2]-AccumEnergy2[k2-1]
            delta_span=cal_dis_meters(6378.137,lat[k2], lng[k2],lat[k2-1], lng[k2-1])
            v_spd=3600*delta_span/(times_list[k2]-times_list[k2-1])        
            if times_list[k2]-times_list[k2-1]<60 and not delta_energy<=0:
                if v_spd>50 :
                    part2_gps.loc[k2,'△距离']=delta_energy*avg_cost
                    part2_gps.loc[k2,'方法']=1_1
                else:
                    part2_gps.loc[k2,'△距离']=delta_span
                    part2_gps.loc[k2,'方法']=1_2
            else:            
                if delta_energy<=0:
                    part2_gps.loc[k2,'△距离']=0
                    part2_gps.loc[k2,'方法']=2
                else:
                    if v_spd>50:
                        part2_gps.loc[k2,'△距离']=delta_energy*avg_cost
                        part2_gps.loc[k2,'方法']=3_1
                    else:
                        part2_gps.loc[k2,'△距离']=max(delta_span,delta_energy*avg_cost)
                        part2_gps.loc[k2,'方法']=3_2
    
                    
        #第三部分距离计算    
        part3.index=[i for i in range(len(part3))]
        part3.loc[0,'△距离']=0
        AccumEnergy3=part3['累积能量[Kwh]'].values
        for k3 in range(1,len(part3)):
            if (AccumEnergy3[k3]-AccumEnergy3[k3-1])>0:
                part3.loc[k3,'△距离']=(AccumEnergy3[k3]-AccumEnergy3[k3-1])*avg_cost
                part3.loc[k3,'方法']=4
            else:
                part3.loc[k3,'△距离']=0
                part3.loc[k3,'方法']=5
        df_out=pd.concat([part1,part2_gps[1:],part3[1:]])
    else:
        part1=df
        part2=df[0:0]
        part3=df[0:0]
        
        #第一部分距离计算    
        part1.index=[i for i in range(len(part1))]
        part1.loc[0,'△距离']=0
        AccumEnergy1=part1['累积能量[Kwh]'].values
        for k1 in range(1,len(part1)):
            if (AccumEnergy1[k1]-AccumEnergy1[k1-1])>0:
                part1.loc[k1,'△距离']=(AccumEnergy1[k1]-AccumEnergy1[k1-1])*avg_cost
                part1.loc[k1,'方法']=4
            else:
                part1.loc[k1,'△距离']=0
                part1.loc[k1,'方法']=5
        df_out=part1.copy()
    
    #计算累积里程
    df_out.loc[0,'累积里程[km]']=0
    df_out.index=[i for i in range(len(df_out))]

    for k in range(1,len(df_out)):
        df_out.loc[k,'累积里程[km]']=df_out.loc[k-1,'累积里程[km]']+df_out.loc[k,'△距离']
    return(df_out)

def calcul_mileage(sn,data_bms,data_gps):

    #合并两张表格
    df_bms=data_bms.copy()
    df_gps=data_gps.copy()
    #删除纬度小于10的点
    for k in range(1,len(df_gps)):
        if df_gps.loc[k,'纬度']<10:
            df_gps=df_gps.drop(k)
    df_bms.set_index(["时间戳"], inplace=True)
    df_gps.set_index(["时间戳"], inplace=True)
    merge_df1=pd.merge(df_bms, df_gps,how='outer', left_index=True, right_index=True)
    merge_df1.loc[:,'时间戳']=merge_df1.index
    merge_df1.index=[i for i in range(len(merge_df1))]

    #参数定义
    cost_min=34 #最小能耗km/kwh
    cost_max=45 #最高能耗km/kwh

    df_input=merge_df1[['时间戳','总电流[A]', '总电压[V]','SOC[%]','充电状态','纬度', '经度']]
    #电流电压数据修复
    df_input=timeconvert(df_input,"时间戳")#计算相对时间
    related_times=df_input['相对时间[s]'].values
    lat_list=df_input['纬度'].values
    lng_list=df_input['经度'].values
    Vlt_list=df_input['总电压[V]'].values
    for k in range(1,len(df_input)):
        if math.isnan(df_input.loc[k,'总电流[A]']):
            if related_times[k]-related_times[k-1]<5:
                df_input.loc[k,'总电流[A]']=df_input.loc[k-1,'总电流[A]']
                df_input.loc[k,'总电压[V]']=df_input.loc[k-1,'总电压[V]']
                df_input.loc[k,'修复']=1
            elif lat_list[k-1]>0:
                delta_odo=cal_dis_meters(6378.137,lat_list[k], lng_list[k],lat_list[k-1], lng_list[k-1])
                df_input.loc[k,'总电流[A]']=1000*3600*(delta_odo/cost_min)/70/(related_times[k]-related_times[k-1])
                df_input.loc[k,'总电压[V]']=70
                df_input.loc[k,'修复']=2
            elif related_times[k]-related_times[k-1]<30:
                df_input.loc[k,'总电流[A]']=df_input.loc[k-1,'总电流[A]']
                df_input.loc[k,'总电压[V]']=df_input.loc[k-1,'总电压[V]']
                df_input.loc[k,'修复']=3
            else:
                df_input=df_input.drop(k)

    df_input.index=[i for i in range(len(df_input))]
    df_input['日期']=[df_input.loc[i,'时间戳'][0:10] for i in range(len(df_input))]     
    date_list=np.unique(df_input['日期'].values)

    list_result=[]
    input_res=pd.DataFrame()
    res = pd.DataFrame()
    df_input_copy=df_input.copy()
    for date_str in date_list:
        df_input_copy=df_input[df_input['日期']==date_str]
        data_len=len(df_input_copy)
        time_list=df_input_copy['时间戳'].values
        #初始化参数
        start_time=datetime.datetime.strptime(time_list[0], "%Y-%m-%d %H:%M:%S")
        last_time=time_list[0]
        reset_time=start_time
        start_index=0
        end_index=1
        cal_count=0
        df_deltaData_last=df_input_copy[0:0]
        #初始化输出
        df_result=pd.DataFrame()
        
        df_result.loc[0,'时间']=start_time
        df_result.loc[0,'时间']=str(df_result.loc[0,'时间'])
        df_result.loc[0,'时间'] =df_result.loc[0,'时间'].rpartition(':')[0]
        
        df_result.loc[0,'累积里程[km]']=0
        df_result.loc[0,'能耗[km/kwh]']=cost_min
        process_store=[]
        avg_cost=34
        cross_odo=0
        for k in range(1,data_len):
            
            target_Time=start_time+datetime.timedelta(minutes=5)
            timenow=datetime.datetime.strptime(time_list[k], "%Y-%m-%d %H:%M:%S")
            if target_Time>=timenow:
                delta_time=(target_Time-timenow).seconds
                cal_flag=0
                if delta_time<60:
                    end_index=k
                    cal_flag=1
            else:        
                end_index=k
                cal_flag=1
            
            if cal_flag==1:
                cal_count=cal_count+1
                
                df_deltaData=df_input_copy[max(start_index-100,0):end_index+1]
                avg_cost=max(cost_min,df_result.loc[cal_count-1,'能耗[km/kwh]'])
                #avg_cost=cost_min
                df_span=real_odo(df_deltaData,avg_cost)
                st_str=df_span['时间戳'].values[0]
                st_time=datetime.datetime.strptime(st_str, "%Y-%m-%d %H:%M:%S")
                last_time_s=datetime.datetime.strptime(last_time, "%Y-%m-%d %H:%M:%S")
                if last_time_s>=st_time:
                    last_time=last_time
                    cross_odo=cross_odo
                else:
                    last_time=start_time
                    cross_odo=0
                delta_odo=df_span['累积里程[km]'].values[-1]-df_span[df_span['时间戳']==str(last_time)]['累积里程[km]'].values[0]
                delta_energy=df_span['累积能量[Kwh]'].values[-1]-df_span[df_span['时间戳']==str(last_time)]['累积能量[Kwh]'].values[0]
                df_result.loc[cal_count,'时间']=timenow
                df_result.loc[cal_count,'时间']=str(df_result.loc[cal_count,'时间'])
                df_result.loc[cal_count,'时间'] = df_result.loc[cal_count,'时间'].rpartition(':')[0]
                
                df_result.loc[cal_count,'累积里程[km]']=df_result.loc[cal_count-1,'累积里程[km]']+delta_odo-cross_odo
                if delta_energy>0:
                    df_result.loc[cal_count,'能耗[km/kwh]']=min(max(delta_odo/delta_energy,cost_min),cost_max)
                else:
                    df_result.loc[cal_count,'能耗[km/kwh]']=cost_min
                
                # df_span[df_span['纬度']>0][-1:]
                if len(df_span[df_span['纬度']>0])>0:
                    last_gps=df_span[df_span['纬度']>0][-1:]
                    idx=last_gps.index.values[0]
                    last_time=df_span.loc[idx,'时间戳']        
                    cross_odo=df_span['累积里程[km]'].values[-1]-df_span.loc[idx,'累积里程[km]']
                else:
                    last_time=df_span['时间戳'].values[-1]        
                    cross_odo=0
                
                start_index=end_index
                start_time=timenow
                cal_flag=0
    
        res=res.append(df_result)
        input_res=input_res.append(df_input_copy)

    l= len(input_res['时间戳'])
    for k in range(l):
        input_res.loc[k,'时间戳'] =input_res.loc[k,'时间戳'].rpartition(':')[0]

    res.index=[i for i in range(len(res))]
    res['日期']=[res.loc[i,'时间'][0:10] for i in range(len(res))]     

    merge_res=pd.DataFrame()
    for date_str in date_list:
        input_res_copy=input_res[input_res['日期']==date_str]
        input_res_copy=input_res_copy.drop_duplicates('时间戳')
        res_copy=res[res['日期']==date_str]
        df_merge=pd.DataFrame()
        df_merge=pd.merge(input_res_copy,res_copy,left_on='时间戳',right_on='时间',how='right')
        merge_res=merge_res.append(df_merge)

    merge_res['sn']=sn
    merge_res=merge_res[['时间戳','sn','总电流[A]','总电压[V]','SOC[%]','充电状态','纬度','经度','能耗[km/kwh]','累积里程[km]']]
    merge_res=merge_res.rename(columns={'累积里程[km]':'每日累积里程[km]'})

    return merge_res





