#!/usr/bin/env python3
try:
    from inmon_utils import *
except:
    import sys
    sys.exit(3)
import argparse
import json
import requests
from requests.adapters import HTTPAdapter, Retry

# Create argument parser itself
parser = argparse.ArgumentParser(description="Pulls information from eyedro")
                                 
# Creates verbose, host, and client flags.
# NOTE: -t --target is used in place of -h --hostname due to the fact that
# ... argparse reserves -h for --help.
parser.add_argument('-H', dest='hostname', help='device hostname', required=True)
parser.add_argument('-t', dest='test', help='test type', required=True, default='none', choices=['cr', 'd1'])
parser.add_argument('-p', dest='port', help='port to check', default='80')
parser.add_argument('-A', dest='nomAmp', help='nominal amperage', default='200')
parser.add_argument('-V', dest='nomVolt', help='nominal voltage', default='120')
parser.add_argument('-P', dest='powerFactor', help='power factor critical and warning low in format crit:warn', default='15:25')
parser.add_argument('-r', dest='retries', help='retries for curl', default='3')
parser.add_argument('-s', dest='secure', help='http or https', action='store_true')


# Parse arguments
args = parser.parse_args()

args.nomAmp = float(args.nomAmp)
args.nomVolt = float(args.nomVolt)
args.retries = int(args.retries)

if (args.port == '80' and args.secure):
    args.port == '443'

pfCritLow, pfWarnLow = args.powerFactor.split(':')
pfCritLow = int(pfCritLow)
pfWarnLow = int(pfWarnLow)

# Amperage thresholds
# Low critical is 0.05% of nominal amperage
# Low warning is 0.4%
# High warning is 80%
# High critical is 100%
ampCritLow = round(args.nomAmp * 0.0005, 2)
ampWarnLow = round(args.nomAmp * 0.004, 2)
ampWarnHigh = round(args.nomAmp * 0.8, 2)
ampCritHigh = round(args.nomAmp, 2)

# Voltage thresholds
# For service entrance
# Low critical is 91.7% of nominal voltage
# Low warning is 95%
# High warning is 105%
# High critical is 105.8%
voltCritLow = round(args.nomVolt * 0.917, 2)
voltWarnLow = round(args.nomVolt * 0.95, 2)
voltWarnHigh = round(args.nomVolt * 1.05, 2)
voltCritHigh = round(args.nomVolt * 1.058, 2)

# Wattage thresholds
# Wattage thresholds are amp thresh * nominal voltage
wattCritLow = ampCritLow * args.nomVolt
wattWarnLow = ampWarnLow * args.nomVolt
wattWarnHigh = ampWarnHigh * args.nomVolt
wattCritHigh = ampCritHigh * args.nomVolt

if (args.secure):
    prefix = "https://"
else:
    prefix = "http://"

url = f"{prefix}{args.hostname}:{args.port}/getdata"

s = requests.Session()

retries = Retry(total=args.retries, backoff_factor=0.5, status_forcelist=[500, 502, 503, 504])
s.mount('http://', HTTPAdapter(max_retries=retries))
s.mount('https://', HTTPAdapter(max_retries=retries))

try:
    response = s.get(url)
except requests.exceptions.ConnectionError as e:
    print(f"A connection error occurred: {e}")
    sys.exit(3)
except requests.exceptions.Timeout:
    print(f"Connection timed out while attempting to reach {url}")
    sys.exit(3)
except requests.exceptions.TooManyRedirects:
    print(f"Connection experienced too many redirects. Likely bad URL {url}")
    sys.exit(3)
except requests.exceptions.RequestException as e:
    print(e)
    sys.exit(3)
    

info = json.loads(response.text)
info = info['data']

if args.test == "cr":
    pfA     = info[2][0]
    voltA   = info[2][1]
    ampA    = info[2][2]
    wattA   = info[2][3]
    pfB     = info[3][0]
    voltB   = info[3][1]
    ampB    = info[3][2]
    wattB   = info[3][3]
elif args.test == "d1":
    pfA     = info[0][0]
    voltA   = info[0][1]
    ampA    = info[0][2]
    wattA   = info[0][3]
    pfB     = info[1][0]
    voltB   = info[1][1]
    ampB    = info[1][2]
    wattB   = info[1][3]

# Convert to SI
pfA = round(pfA/10, 2)
voltA = round(voltA/100, 2)
ampA = round(ampA/1000, 2)
pfB = round(pfB/10, 2)
voltB = round(voltB/100, 2)
ampB = round(ampB/1000, 2)
# Watts are already in SI

textCrit = ""
textWarn = ""
textUnkn = ""
textOut = ""
dataOut = ""
outString = ""
returnStat = 0

if pfA < pfCritLow:
    textCrit += "L1 PF; "
elif pfA < pfWarnLow:
    textWarn += "L1 PF; "
elif pfA >= pfWarnLow:
    pass
else:
    textUnkn += "L1 PF; "

if voltA >= voltWarnLow and voltA <= voltWarnHigh:
    pass
elif voltA < voltCritLow or voltA > voltCritHigh:
    textCrit += "L1 Voltage; "
elif voltA < voltWarnLow or voltA > voltWarnHigh:
    textWarn += "L1 Voltage; "
else:
    textUnkn += "L1 Voltage; "

if ampA >= ampWarnLow and ampA <= ampWarnHigh:
    pass
elif ampA < ampCritLow or ampA > ampCritHigh:
    textCrit += "L1 Amperage; "
elif ampA < ampWarnLow or ampA > ampWarnHigh:
    textWarn += "L1 Amperage; "
else:
    textUnkn += "L1 Amperage; "

if wattA >= wattWarnLow and wattA <= wattWarnHigh:
    pass
elif wattA < wattCritLow or wattA > wattCritHigh:
    textCrit += "L1 Wattage; "
elif wattA < wattWarnLow or wattA > wattWarnHigh:
    textWarn += "L1 Wattage; "
else:
    textUnkn += "L1 Wattage; "


if pfB < pfCritLow:
    textCrit += "L2 PF; "
elif pfB < pfWarnLow:
    textWarn += "L2 PF; "
elif pfB >= pfWarnLow:
    pass
else:
    textUnkn += "L2 PF; "

if voltB >= voltWarnLow and voltB <= voltWarnHigh:
    pass
elif voltB < voltCritLow or voltB > voltCritHigh:
    textCrit += "L2 Voltage; "
elif voltB < voltWarnLow or voltB > voltWarnHigh:
    textWarn += "L2 Voltage; "
else:
    textUnkn += "L2 Voltage; "

if ampB >= ampWarnLow and ampB <= ampWarnHigh:
    pass
elif ampB < ampCritLow or ampB > ampCritHigh:
    textCrit += "L2 Amperage; "
elif ampB < ampWarnLow or ampB > ampWarnHigh:
    textWarn += "L2 Amperage; "
else:
    textUnkn += "L2 Amperage; "

if wattB >= wattWarnLow and wattB <= wattWarnHigh:
    pass
elif wattB < wattCritLow or wattB > wattCritHigh:
    textCrit += "L2 Wattage; "
elif wattB < wattWarnLow or wattB > wattWarnHigh:
    textWarn += "L2 Wattage; "
else:
    textUnkn += "L2 Wattage; "

avg_pf = round((pfA+pfB)/2, 2)
avg_volt = round((voltA+voltB)/2, 2)
avg_amp = round((ampA+ampB)/2, 2)
avg_watt = round((wattA+wattB)/2, 2)

textOut += f"{avg_pf}% PF : {avg_volt}V : {avg_amp}A : {avg_watt}W"
dataOut += f"L1_pf={pfA}%;{pfWarnLow}:101;{pfCritLow}:105; "
dataOut += f"L1_voltage={voltA};{voltWarnLow}:{voltWarnHigh};{voltCritLow}:{voltCritHigh}; "
dataOut += f"L1_amperage={ampA};{ampWarnLow}:{ampWarnHigh};{ampCritLow}:{ampCritHigh}; "
dataOut += f"L1_wattage={wattA};{wattWarnLow}:{wattWarnHigh};{wattCritLow}:{wattCritHigh}; "
dataOut += f"L2_pf={pfB}%;{pfWarnLow}:101;{pfCritLow}:105; "
dataOut += f"L2_voltage={voltB};{voltWarnLow}:{voltWarnHigh};{voltCritLow}:{voltCritHigh}; "
dataOut += f"L2_amperage={ampB};{ampWarnLow}:{ampWarnHigh};{ampCritLow}:{ampCritHigh}; "
dataOut += f"L2_wattage={wattB};{wattWarnLow}:{wattWarnHigh};{wattCritLow}:{wattCritHigh}; "

if textCrit != "" or textWarn != "" or textUnkn != "":
    if textCrit != "":
        outString += f"CRITICAL - {textCrit} - "
        returnstat = max(returnStat, 2)
    if textUnkn != "":
        outString += f"UNKNOWN - {textUnkn} - "
        returnstat = max(returnStat, 3)
    if textWarn != "":
        outString += f"WARNING - {textWarn} - "
        returnstat = max(returnStat, 1)
else:
    outString += "OK - "

outString += " "
outString += textOut
outString += " | "
outString += dataOut

print(outString)
sys.exit(returnStat)
