#!/usr/bin/python3 -u
"""
Description: CyberPower UPS daemon
Author: thnikk
"""
import argparse
import time
from subprocess import run
import hid


def parse_args() -> argparse.ArgumentParser:
    """ Parse arguments """
    parser = argparse.ArgumentParser(description="CyberPower UPS module")
    parser.add_argument(
        '-v', '--vendor', action='store', type=str,
        default='0764', help='Vendor ID')
    parser.add_argument(
        '-p', '--product', action='store', type=str,
        default='0501',  help='Product ID')
    parser.add_argument(
        '-d', '--delay', type=int, default=60,
        help='Delay before shutdown on power loss')
    parser.add_argument(
        '--dry', action='store_true', help="Disable action on power loss")
    return parser.parse_args()


class CyberPower:
    """ Class for CyberPower UPS """
    def __init__(self, vendor, product) -> None:
        self.device = hid.Device(
            path=hid.enumerate(vendor, product)[0]['path'])

    def status_report(self):
        """ Get status report """
        return self.device.get_feature_report(0x0b, 3)[1]

    def ac(self) -> bool:
        """ AC status """
        return bool(self.status_report() & 1)

    def close(self) -> None:
        """ Close device """
        self.device.close()


def main():
    """ Main function """
    args = parse_args()

    for x in range(1, 5):
        try:
            ups = CyberPower(int(args.vendor, 16), int(args.product, 16))
            print('Connected to UPS')
            break
        except hid.HIDException:
            print(f"Couldn't connect, trying again (attempt {x})")
            time.sleep(3)

    count = 0
    try:
        while True:
            while ups.ac():
                if count:
                    print('Power restored.')
                count = 0
                time.sleep(10)
            while not ups.ac():
                if not count:
                    print('Lost power, waiting...')
                count += 1
                if count > args.delay:
                    raise ValueError
                time.sleep(1)
    except ValueError:
        print("Shutdown")
        ups.close()
        if not args.dry:
            run(['systemctl', 'poweroff'], check=True)


if __name__ == "__main__":
    main()
