#!/usr/bin/env python3
import include_homekit
import asyncio
import logging

from datetime import datetime
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from typing import Optional
from argparse import ArgumentParser
from homekit.config import config
from homekit.mqtt import MqttNodesConfig, MqttNode, MqttWrapper
from homekit.mqtt.module.temphum import MqttTempHumModule, MqttTemphumDataPayload, DATA_TOPIC
from homekit.temphum import SensorType, BaseSensor
from homekit.temphum.i2c import create_sensor

_logger = logging.getLogger(__name__)
_sensor: Optional[BaseSensor] = None
_lock = asyncio.Lock()
_mqtt: MqttWrapper
_mqtt_ndoe: MqttNode
_mqtt_temphum: MqttTempHumModule
_stopped = True
_scheduler = AsyncIOScheduler()
_sched_task_added = False


async def get_measurements():
    async with _lock:
        temp = _sensor.temperature()
        rh = _sensor.humidity()

        return rh, temp


def on_mqtt_connect():
    global _stopped, _sched_task_added
    _stopped = False

    if not _sched_task_added:
        _scheduler.add_job(on_sched_task, 'interval', seconds=60, next_run_time=datetime.now())
        _scheduler.start()
        _sched_task_added = True
    elif _scheduler:
        _scheduler.resume()


def on_mqtt_disconnect():
    global _stopped
    _stopped = True

    if _scheduler:
        _scheduler.pause()


async def on_sched_task():
    if _stopped:
        return

    rh, temp = await get_measurements()
    payload = MqttTemphumDataPayload(temp=temp, rh=rh)
    _mqtt_node.publish(DATA_TOPIC, payload.pack())


if __name__ == '__main__':
    parser = ArgumentParser()
    parser.add_argument('--node-id',
                        type=str,
                        required=True,
                        choices=MqttNodesConfig().get_nodes(only_names=True),
                        help='node id must be defined in the config')
    args = config.load_app(parser=parser)

    node_cfg = MqttNodesConfig()[args.node_id]
    _sensor = create_sensor(SensorType(node_cfg['temphum']['module']),
                            int(node_cfg['temphum']['i2c_bus']))

    _mqtt = MqttWrapper(client_id=args.node_id)
    _mqtt.add_connect_callback(on_mqtt_connect)
    _mqtt.add_disconnect_callback(on_mqtt_disconnect)

    _mqtt_node = MqttNode(node_id=args.node_id,
                          node_secret=MqttNodesConfig.get_node(args.node_id)['password'])
    _mqtt.add_node(_mqtt_node)

    _mqtt_temphum = _mqtt_node.load_module('temphum')

    try:
        _mqtt.connect_and_loop(loop_forever=True)

    except (KeyboardInterrupt, SystemExit):
        if _scheduler:
            _scheduler.shutdown()
        _logger.info('Exiting...')

    finally:
        _mqtt.disconnect()