# -*- coding: utf-8 -*-
# SPDX-License-Identifier: EUPL-1.2
#  
#  Copyright (c) 2022-2024  Marc van der Sluys - Nikhef/Utrecht University - marc.vandersluys.nl
#   
#  This file is part of the sluyspy Python package:
#  Marc van der Sluys' personal Python modules.
#  See: https://github.com/MarcvdSluys/sluyspy
#   
#  This is free software: you can redistribute it and/or modify it under the terms of the European Union
#  Public Licence 1.2 (EUPL 1.2).  This software is distributed in the hope that it will be useful, but
#  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
#  PURPOSE.  See the EU Public Licence for more details.  You should have received a copy of the European
#  Union Public Licence along with this code.  If not, see <https://www.eupl.eu/1.2/en/>.


"""Solar-panel functions for the sluyspy package"""


import pandas as _pd
import pytz as _tz
import solarenergy as _se
from sluyspy import env as _env

# My computing environment:
_env = _env.environment()

# My solar-panel specs:
specs = _se.read_solar_panel_specs()


def read_detailed_log(file_name='Current/detailed-log.csv', last_only=None, header=None, sun_position=False, rem_cols=True, no_p0rows=False, no_elec=False, no_cond=True):
    """Read solar-panel detailed-log.csv and select the useful data.
    
    Parameters:
      file_name (str):      Name of the input file (optional; default=None -> detailed-log.csv).
      header (int):         Number of lines to consider as header and skip (optional; default: 0).
      last_only (int):      Number of last lines to read.  This tails the last lines into a separate file and reads that.
      sun_position (bool):  Add (compute) Sun position to the data (slow! - optional; default: False).
      rem_cols (bool):      Remove default columns (constants, duplicates, uninteresting).
      no_p0rows (bool):     Remove rows without power (P=0; Relay=closed; Cond!=OK).
      no_elec (bool):       Remove electricity details (some P,V,I, f).
      no_cond (bool):       Remove condition/status columns (Cond, Relay, Tinv).
      
    Returns:
      (pandas.DataFrame):  DataFrame containing solar-panel data.
    """
    
    col_names = ['date', 'time', 'SN1', 'Type', 'SN2', 'Pdc', 'x0', 'Idc', 'x1', 'Vdc', 'x2', 'Pac', 'x3', 'x4', 'Iac', 'x5', 'x6', 'Vac',
                 'x7', 'x8', 'Pdc2', 'Pac2', 'x9', 'Eday', 'Etot', 'Freq', 't_oper', 't_feedin', 'Btooth', 'Cond', 'Relay', 'Tinv']
    
    # Issue: detailed-log.csv becomes very long -> reading is slow.  Tail the last 3000 lines/minutes (2+
    # days) to a shorter file and read that (currently saves a factor 17 on CPU time (2022-11-12)):
    if last_only is not None:
        from pathlib import Path
        import sluyspy.system as ssys
        
        tmpfile = ssys.temp_file_name(_env.sp_dir+'Current',  '.detailed-log-last', 'csv')
        
        ssys.tail_file(_env.sp_dir+file_name, tmpfile, last_only)  # Copy last last_only lines to tmpfile
        df = _pd.read_csv(tmpfile, header=header, sep=r'\s*,\s*', engine='python', names=col_names)
        
        Path.unlink(Path(tmpfile))  # Remove temporary file
        
    else:
        df = _pd.read_csv(_env.sp_dir+file_name, header=header, sep=r'\s*,\s*', engine='python', names=col_names)
    
    # Remove unwanted columns:
    if rem_cols:
        del df['SN1'], df['SN2'], df['Type']  # Not interesting - constant
        del df['Pdc2'], df['Pac2']            # Not interesting - duplicates
        del df['x0'], df['x1'], df['x2'], df['x3'], df['x4'], df['x5'], df['x6'], df['x7'], df['x8'], df['x9']  # x_i are always 0
        
        del df['Eday'], df['t_oper'], df['t_feedin'], df['Btooth']  # Not interested in now  # , df['Etot']
        
    
    # Remove rows witout power (P=0; Relay=closed; Cond!=OK):
    if no_p0rows:
        df = df[df['Relay'] == 'Closed']  # Only keep data when the relay is closed (i.e., providing a current/energy)
        df = df[df['Cond']  == 'Ok']      # Only keep data when the condition is 'OK'
        df = df[df['Pdc']  > 0]           # Only keep data if there is power
        df = df[df['Pac']  > 0]           # Only keep data if there is power
        
        # df = df[df['Pac']  < 2990]        # Only keep data for P < 3kW, since 3kW may indicate >3kW
        # df = df[df['Tinv'] > 0]           # Only keep data if we have a temperature (of the inverter!)
        
        # No longer needed:
        del df['Relay'], df['Cond'], df['Tinv']
        
    elif no_cond:
        del df['Cond'], df['Relay'], df['Tinv']
    
    # Slightly more accurate: ~3-4 significant digits -> 4-5:
    df['Pdc'] = df['Idc'] * df['Vdc']
    df['Pac'] = df['Iac'] * df['Vac']
    
    if no_elec:
        del df['Pdc'], df['Idc'], df['Vdc'], df['Iac'], df['Vac'], df['Freq']

    
    
    # Combine date and time columns to a timezone-aware datetime:
    df['date'] = _pd.DatetimeIndex(_pd.to_datetime(df['date']+' '+df['time']))
    df = df.rename(columns={'date': 'dtm'})  # Rename column date -> dtm
    # df['dtm'] = df['dtm'].dt.round('min')
    mytz = _tz.timezone(specs.tz)
    df.dtm = df.dtm.dt.tz_localize(mytz)  # Timezone naive -> timezone aware.  Indicate that the existing times are in mytz, without conversion.
    
    del df['time']  # Remove column 'time'
    
    # print(df['dtm'])
    
    # Compute Sun position (uses SolTrack behind the scenes):
    if sun_position:
        df['sunAz'],df['sunAlt'],df['sunDist'] = \
            _se.sun_position_from_datetime(specs.geo_lon,specs.geo_lat, df['dtm'])
        
    return df


def write_day_file(df, subdir='', prefix=specs.name, ext='csv', verbosity=0):
    """Write one day of (e.g.) minutely solar-panel data to daily file named 'subdir/prefix-yyyymmdd.ext'.
    
    Parameters:
      df (pandas.DataFrame):  Pandas DataFrame with columns datetime, Pac and Etot.
      subdir (str):           Subdirectory to save file in, with trailing slash.
      prefix (str):           File name prefix (defaults to name of the plant, followed by a hyphen).
      ext (str):              File extension to use.
      verbosity (int):        Verbosity (0-2; defaults to 0).
    """
    
    if len(df) < 1:
        if verbosity > 0:  print('No data available, no file created.')
        return
    
    
    # Want separate date and time columns:
    df['date'] = df.dtm.dt.date
    df['time'] = df.dtm.dt.time
    
    date = df.loc[:, 'dtm'].dt.date.iloc[0].strftime('%Y%m%d')  # .loc[0, ''] doesn't work, since row 0 does not exist
    out_file_name = _env.sp_dir+subdir+prefix+'-'+date+'.'+ext
    if verbosity > 0:  print('Saving data to '+out_file_name)
        
    # Open file and write header:
    out_file = open(out_file_name, 'w')
    out_file.write('sep=;\n')
    out_file.write('Version CSV1|Tool SBFspot3.3.1 (Linux)|Linebreaks CR/LF|Delimiter semicolon|Decimalpoint dot|Precision 3\n')
    out_file.write('\n')
    out_file.write(';SN: '+specs.inv_sn+';SN: '+specs.inv_sn+'\n')
    out_file.write(';'+specs.inv_model+';'+specs.inv_model+'\n')
    out_file.write(';'+specs.inv_sn+';'+specs.inv_sn+'\n')
    out_file.write(';Total yield;Power\n')
    out_file.write(';Counter;Analog\n')
    out_file.write('yyyy-MM-dd;HH:mm:ss;kWh;kW\n')
    
    for row in df.iterrows():
        ser = row[1]
        if verbosity > 1:  print('%s;%s;%0.3f;%5.3f' % (ser.date, ser.time, ser.Etot, ser.Pac))
        
        out_file.write('%s;%s;%0.3f;%5.3f\n' % (ser.date, ser.time, ser.Etot, ser.Pac/1e3))  # Pac: W -> kW
        
    out_file.close()
    
    return    


