#!/usr/bin/env python3

from suntime import Sun
import argparse
import configparser
import requests
import sys
import time

parser = argparse.ArgumentParser()
parser.add_argument("-s",
                  "--status",
                  action="store_true",
                  dest="printStatus",
                  help="Print Status Information",
                  default=False)
parser.add_argument("-f",
                  "--force",
                  action="store_true",
                  dest="force",
                  help="Force retrieval of Power value",
                  default=False)
args = parser.parse_args()


def isDaylight(lat, lon, toleranceSeconds):
    daylight = False
    sun = Sun(lat, lon)
    sunriseTimestamp = int(sun.get_local_sunrise_time().timestamp())
    sunsetTimestamp = int(sun.get_local_sunset_time().timestamp())
    nowTimestamp = int(time.time())

    if ((sunriseTimestamp + toleranceSeconds) < nowTimestamp) and (
        (sunsetTimestamp - toleranceSeconds) > nowTimestamp):
        daylight = True

    return daylight


# Query all relevant System Information in one Session
def retrieveData(userName, password, stationId):
    with requests.Session() as s:
        try:
            r = s.post('https://www.envertecportal.com/apiaccount/login',
                       data={
                           'userName': userName,
                           'pwd': password
                       },
                       timeout=(20, 40))

            r = s.post(
                'https://www.envertecportal.com/ApiStations/getStationInfo',
                data={
                    'stationId': stationId
                },
                timeout=(20, 60)).json()
            power = r['Data']['Power']

            # ignores paging for now, inputs are website defaults
            r = s.post(
                'https://www.envertecportal.com/ApiInverters/QueryTerminalReal',
                data={
                    'page': 1,
                    'perPage': 20,
                    'orderBy': 'GATEWAYSN',
                    'whereCondition': f"{{\"STATIONID\":\"{stationId}\"}}"
                },
                timeout=(10, 60)).json()
            powerDetails = r['Data']['QueryResults']

            r = s.post('https://www.envertecportal.com/apiAccount/Logout',
                       timeout=(20, 40))

        # connect timeouts occur so frequently since the portal relaunch,
        # ignore them for the time beeing completely
        except requests.exceptions.ConnectTimeout as eTimeout:
            sys.exit(1)
        except requests.exceptions.RequestException as e:
            print(e)
            raise SystemExit(e)

    return float(power), powerDetails


# use our stateFile to determine if we have a state change
# used to decide if we print something - thus generate a mail - later on
def stateCheck(newState, stateFile):
    try:
        with open(stateFile, "r") as f:
            oldState = f.read()
    except FileNotFoundError:
        oldState = "NULL"

    if newState == oldState:
        change = False
    else:
        change = True
        with open(stateFile, "w") as f:
            f.write(newState)

    return change

def panelPrint(currentPower):
    print(f"Total Power: {currentPower[0]}")
    for panel in currentPower[1]:
        print(f"{panel['SNALIAS']}: {panel['POWER']} - {panel['SITETIME']}")


# read configuration file
conf = configparser.ConfigParser()
conf.read('portalmonitor.ini')

# retrieve current power value as reported by envertecportal
if isDaylight(conf['config'].getfloat('lat'), conf['config'].getfloat('lon'),
              conf['config'].getint('toleranceSeconds')) or args.force:
    currentPower = retrieveData(conf['config']['userName'],
                                   conf['config']['password'],
                                   conf['config']['stationId'])

    if args.printStatus:
        panelPrint(currentPower)
        sys.exit(0)

    if currentPower[0] == 0:
        if stateCheck('FAILED', conf['config']['stateFile']):
            print('Error: Power dropped to 0 but we should have daylight!')
            panelPrint(currentPower)
        sys.exit(1)
    else:
        if stateCheck('OK', conf['config']['stateFile']):
            print('Resolved')
            panelPrint(currentPower)
        sys.exit(0)