#! /usr/bin/env python3

"""Encode and schedule DL messages to manage TG-LRX2 configuration"""

import sys
import argparse
import logging
import json
import yaml
import paho.mqtt.publish as publish

log = logging.getLogger(__name__)
log_paho = logging.getLogger("paho")


class Application:
    def __init__(self, app_id, host, port=1883, append=False, confirm=False, user="", passwd=""):
        self.app_id = app_id
        self.host = host
        self.port = port
        self.append = append
        self.confirmed_dl = bool(confirm)
        self.auth = {'username': user, 'password': passwd}
        log.debug(f"mqtt: {self.host}:{self.port}")

    def publish(self, dev_id, dl_messages):
        topic = f"v3/{self.app_id}/devices/{dev_id}/down/" + ("push" if self.append else "replace")
        log.debug(f"mqtt topic: {topic}")

        dl_list = []
        for dl in dl_messages:
            dl_list.append(
                {"f_port": dl['port'], "frm_payload": dl['b64'], "priority": "HIGH", "confirmed": self.confirmed_dl})
            log.debug(f"downlink: {dl_list[-1]}")

        downlink = json.dumps({"downlinks": dl_list})
        publish.single(topic, downlink, hostname=self.host, port=self.port, auth=self.auth)


def main():
    parser = argparse.ArgumentParser(description="TG-LRX2 DL scheduler")
    parser.add_argument("-v", type=str, default="ERROR", metavar="LEVEL",
                        help="Log level (ERROR, WARN, INFO, DEBUG).")
    parser.add_argument("--host", type=str, default=None, metavar="HOST.yml",
                        required=True, help="Host configuration, credentials")
    parser.add_argument("--confirm", action=argparse.BooleanOptionalAction,
                        help="Send confirmed downlink messages")
    parser.add_argument("--append", action=argparse.BooleanOptionalAction,
                        help="Instead of clearing DL queue - append messages")
    parser.add_argument("--dl-msg", type=str, default=None, metavar="DL-MSG.yml",
                        required=True, help="Downlink messages to send")
    parser.add_argument("device", nargs='+', type=str, metavar="device-id", default=None,
                        help="Device IDs to publish messages to")
    args = parser.parse_args()

    log_fmt = '%(asctime)s.%(msecs)03d: %(module)s <%(levelname)s>: %(message)s'
    logging.basicConfig(level="ERROR",
                        format=log_fmt,
                        datefmt='%m/%d %H:%M:%S')
    log.setLevel(args.v)
    log_paho.setLevel(args.v)

    host_cfg_file = open(args.host, "r")
    cfg = yaml.load(host_cfg_file, Loader=yaml.FullLoader)

    dl_msg_file = open(args.dl_msg, "r")
    dl_msgs = yaml.load(dl_msg_file, Loader=yaml.FullLoader)

    ttn_broker = Application(cfg['app-id'], cfg['host'], cfg['port'], args.append, args.confirm,
                             cfg['user'], cfg['password'])

    for dev in args.device:
        ttn_broker.publish(dev, dl_msgs)

    return 0


if __name__ == '__main__':
    sys.exit(main())
