# AUTOGENERATED! DO NOT EDIT! File to edit: ../00_core.ipynb.

# %% auto 0
__all__ = ['Emissions', 'EM6']

# %% ../00_core.ipynb 3
from fastcore.utils import *
import httpx
import pandas as pd
import numpy as np
import json

# %% ../00_core.ipynb 4
class Emissions():
    def __init__(self):
        self.ea_eif = pd.concat([(pd.read_csv('https://www.emi.ea.govt.nz/Wholesale/Datasets/_AdditionalInformation/SupportingInformationAndAnalysis/2021/20210419_EAF_Data/EIF/EIF.csv')
                        .pipe(lambda df: df.loc[df.Type!='C_HYD',:'emission_intensity_kgCO2/MWh']) # these are from EM6 Carbon Methodology and are HYDRO but oer is set to 614 https://www.ems.co.nz/em6-carbon-methodology/#:~:text=em6%20Carbon%20Methodology,valuable%20feature%20for%20NZ%20consumers.
                        .set_axis(['node_id','oer'], axis=1)
                        .assign(oer = lambda df_: df_.oer/1000)), # set to kgCO2/kwh
                        pd.DataFrame({'node_id':['KIN0112 KIN0','KPA1101 KPI1','HWA1101 WAA1','HWA1102 WAA2'],# these are from EM6 Carbon Methodology
                                              'oer':[1.092,0.502,0.502,0.502]})]).reset_index(drop= True)        
                

# %% ../00_core.ipynb 6
class EM6(Emissions):
    def __init__(self,client_id,username,password):
        self.client_id = client_id
        self.username = username
        self.password = password
        super().__init__()
        self._auth()
        self.nodes = (self.nodes().merge(self.ea_eif, how='left')
                                .assign(oer = lambda df_: np.where((df_.generation_type_name == 'Hydro')|(df_.generation_type_name == 'Wind'),0,df_.oer))
                                .assign(oer = lambda df_: np.where((df_.generation_type_name == 'Battery'),0.1,df_.oer))) # this is a hack but it works and can be refined later
        # self.node_id_name = {x.node_id: x.node_name for x in self.nodes.itertuples()}
        # self.fuel_id_name = {x.generation_type_id: x.generation_type_name for x in self.nodes.itertuples()}
    
    def _auth(self):
        url= "https://api.em6.co.nz/auth"
        data = "{\"AuthParameters\":{\"USERNAME\":\""+ self.username +"\",\"PASSWORD\":\"" + self.password + "\"},\"AuthFlow\":\"USER_PASSWORD_AUTH\",\"ClientId\":\""+self.client_id+"\"}"
        headers = {
            'content-type': "text/plain",
            'cache-control': "no-cache"
            }
        try:
            res = httpx.post(url, data=data, headers=headers)
        except httpx.exceptions.RequestException as e:  # This is the correct syntax
            raise SystemExit(e)
        self.token = res.json()['AuthenticationResult']['IdToken']
        return

    def nodes(self):
        url = 'https://api.em6.co.nz/ords/em6/data_api/nodes'
        headers = {'Authorization': '{}'.format(self.token)}
        params = {}
        try:
            res = httpx.get(url, headers=headers, params= params)
        except httpx.exceptions.RequestException as e:  # This is the correct syntax
            raise SystemExit(e)
        nodes = pd.DataFrame.from_dict(json.loads(res.content)['items'])
        for col in ['pricing_node','load_node','conforming_load','generation_node']:
            nodes[col] = nodes[col] == 'TRUE'
        # self.node_id_name = {x.site_id: x.site_name for x in nodes.drop_duplicates('site_id').itertuples()}
        # self.site_id_coords = {x.site_id: [x.longitude, x.lattitude] for x in nodes.drop_duplicates('site_id').itertuples()}
        # self.name_id = {x.site_name: x.site_id for x in nodes.drop_duplicates('site_id').itertuples()}
        gen_cols = ['site_id', 'site_name','node_id','node_name','grid_zone_id','grid_zone_name',
            'generation_type_id', 'generation_type_name','generation_capacity_mw','lattitude','longitude']
        self.gen_nodes = (nodes
                        [nodes.generation_node]
                        .loc[:,gen_cols]
                        ).reset_index(drop=True)
        return 
    
    @staticmethod
    def days_ago(days_ago = 0):
        days_ago = datetime.datetime.today() - datetime.timedelta(days=days_ago)
        return days_ago

    def hvdc(self,
              startdate=None, 
              enddate=None, 
              melt=False):
        '''
        Choices are load / generation / hvdc
        '''
        # self._auth()
        headers = {'Authorization': '{}'.format(self.token)}
        params = {}

        params['from_trading_date'] =  str(startdate.strftime("%d/%m/%Y"))       
        params['to_trading_date'] = str(enddate.strftime("%d/%m/%Y"))  
        res = httpx.get(f'https://api.em6.co.nz/ords/em6/data_api/scada_hvdc', 
                           headers=headers, params= params)
        df = pd.DataFrame.from_dict(json.loads(res.content)['items'])
        df['trading_date'] = pd.to_datetime(df['trading_date'],dayfirst=True)
        df = df.drop(columns=['tp49_mw','tp50_mw'])

        if melt:
            df = pd.melt(df, id_vars=[ 'node_id', 'node_name' , 'trading_date', 'mean_energy_mw'],
                         value_vars=[x for x in df.columns if 'tp' in x])
            df = (df
                  .assign(timestamp = lambda df_: df_.trading_date +
                                              pd.to_timedelta((df_.variable.str[2:-3:].astype(int)-1)*30,'m'),
                          variable = lambda df_ : df_.variable.str[2:-3:].astype(int))
                  .rename(columns={'variable': 'tp','value': 'mw'})
                 )
#             df= df.merge(self.nodes())
            df= df.set_index('timestamp')

        return df

    def scada(self,
              data='load', 
              node=None, 
              startdate=None, 
              enddate=None, 
              melt=False):
        '''
        Choices are load / generation / hvdc
        '''
        # self._auth()
        headers = {'Authorization': '{}'.format(self.token)}
        params = {}

        url_ext = f'/{node}' if node else ''

        params['from_trading_date'] =  str(startdate.strftime("%d/%m/%Y"))       
        params['to_trading_date'] = str(enddate.strftime("%d/%m/%Y"))  
        res = httpx.get(f'https://api.em6.co.nz/ords/em6/data_api/scada_{data}{url_ext}', 
                           headers=headers, params= params)
        df = pd.DataFrame.from_dict(json.loads(res.content)['items'])
        df['trading_date'] = pd.to_datetime(df['trading_date'],dayfirst=True)
        df = df.drop(columns=['tp49_mw','tp50_mw'])

        if melt:
            df = pd.melt(df, id_vars=[ 'node_id', 'node_name' , 'trading_date', 'mean_energy_mw'],
                         value_vars=[x for x in df.columns if 'tp' in x])
            df = (df
                  .assign(timestamp = lambda df_: df_.trading_date +
                                              pd.to_timedelta((df_.variable.str[2:-3:].astype(int)-1)*30,'m'),
                          variable = lambda df_ : df_.variable.str[2:-3:].astype(int))
                  .rename(columns={'variable': 'tp','value': 'mw'})
                 )
#             df= df.merge(self.nodes())
            df= df.set_index('timestamp')

        return df

    def scada_generation(self,
              startdate=None, 
              enddate=None):
        '''
        Choices are load / generation / hvdc
        '''
        # self._auth() #already done in self.scada
        headers = {'Authorization': '{}'.format(self.token)}
        params = {}


        params['from_trading_date'] =  str(startdate.strftime("%d/%m/%Y"))       
        params['to_trading_date'] = str(enddate.strftime("%d/%m/%Y"))  
        res = httpx.get(f'https://api.em6.co.nz/ords/em6/data_api/scada_generation', headers=headers, params= params)
        df = pd.DataFrame.from_dict(json.loads(res.content)['items'])
        df['trading_date'] = pd.to_datetime(df['trading_date'],dayfirst=True)
        df = df.drop(columns=['tp49_mw','tp50_mw'])

        df = pd.melt(df, id_vars=['island', 'node_id', 'node_name' , 'trading_date', 'mean_energy_mw'],  value_vars=[x for x in df.columns if 'tp' in x])
        df = (df
                .assign(timestamp = lambda df_: df_.trading_date +  pd.to_timedelta((df_.variable.str[2:-3:].astype(int)-1)*30,'m'),
                        variable = lambda df_ : df_.variable.str[2:-3:].astype(int))
                .rename(columns={'variable': 'tp','value': 'mw'})
                .merge(self.nodes.loc[:,['node_id','site_id','oer','generation_type_id','generation_type_name','lattitude','longitude']], how='left', on='node_id')
                .assign(proportion = lambda df: df.groupby(['timestamp','site_id','generation_type_id']).mw.transform(sum)/df.groupby(['timestamp','site_id']).mw.transform(sum))
            )

        return df

    def raw_scada(self,
              startdate=None, 
              enddate=None):
        headers = {'Authorization': '{}'.format(self.token)}
        params = {}

        params['from_trading_date'] =  str(startdate.strftime("%d/%m/%Y"))       
        params['to_trading_date'] = str(enddate.strftime("%d/%m/%Y"))  
        res = httpx.get(f'https://api.em6.co.nz/ords/em6/data_api/scada_hvdc', 
                           headers=headers, params= params)
        hvdc = (pd.DataFrame.from_dict(json.loads(res.content)['items'])
              .assign(trading_date = lambda df : pd.to_datetime(df.trading_date,dayfirst=True))
              .drop(columns=['tp49_mw','tp50_mw'])
              .pipe(self.melted)
              .assign(timestamp = lambda df_: df_.trading_date +
                                    pd.to_timedelta((df_.variable.str[2:-3:].astype(int)-1)*30,'m'),
                      variable = lambda df_ : df_.variable.str[2:-3:].astype(int))
              .drop(columns=['trading_date','variable'])
              .rename(columns={'value': 'mw'})
               )
        res = httpx.get(f'https://api.em6.co.nz/ords/em6/data_api/scada_generation', headers=headers, params= params)
        gen = (pd.DataFrame.from_dict(json.loads(res.content)['items'])
              .assign(trading_date = lambda df : pd.to_datetime(df.trading_date,dayfirst=True))
              .drop(columns=['country','tp49_mw','tp50_mw'])
              .pipe(self.melted)
              .assign(timestamp = lambda df_: df_.trading_date + pd.to_timedelta((df_.variable.str[2:-3:].astype(int)-1)*30,'m'),
                      variable = lambda df_ : df_.variable.str[2:-3:].astype(int))
              .drop(columns=['trading_date','variable'])
              .rename(columns={'value': 'gen_mw'})
               )        
        res = httpx.get(f'https://api.em6.co.nz/ords/em6/data_api/scada_load', headers=headers, params= params)
        load = (pd.DataFrame.from_dict(json.loads(res.content)['items'])
              .assign(trading_date = lambda df : pd.to_datetime(df.trading_date,dayfirst=True))
              .drop(columns=['country','tp49_mw','tp50_mw'])
              .pipe(self.melted)
              .assign(timestamp = lambda df_: df_.trading_date + pd.to_timedelta((df_.variable.str[2:-3:].astype(int)-1)*30,'m'))
              .drop(columns=['trading_date','variable'])
              .rename(columns={'value': 'load_mw'})
               )                

        return load, gen, hvdc

    def melted(self, df):
        return pd.melt(df, id_vars=['island' ,'node_id', 'node_name' , 'trading_date'],#, 'mean_energy_mw'],
                         value_vars=[x for x in df.columns if 'tp' in x])

    def current_generation(self):
        headers = {'Authorization': '{}'.format(self.token)}
        params = {}

        res = httpx.get(f'https://api.em6.co.nz/ords/em6/data_api/current_generation', headers=headers, params= params)
        df = pd.DataFrame.from_dict(json.loads(res.content)['items'])
        return df

    def current_load(self):
        headers = {'Authorization': '{}'.format(self.token)}
        params = {}

        res = httpx.get(f'https://api.em6.co.nz/ords/em6/data_api/current_load', headers=headers, params= params)
        df = pd.DataFrame.from_dict(json.loads(res.content)['items'])
        return df

    def current_hvdc(self):
        headers = {'Authorization': '{}'.format(self.token)}
        params = {}

        res = httpx.get(f'https://api.em6.co.nz/ords/em6/data_api/current_hvdc', headers=headers, params= params)
        df = pd.DataFrame.from_dict(json.loads(res.content)['hvdc_flow'])
        return df
