#!/usr/bin/python3
"""
@file
@copyright
  (c) Copyright ESO - European Southern Observatory, 2022
  All Rights Reserved
  ESO (eso.org) is an Intergovernmental Organisation, and therefore
  special legal conditions apply.
@author N. Benes

@brief Simulator of ptpmond/ntpmon local interface to test client applications
"""

from inspect import cleandoc
import logging
import os
import signal
from sys import stdin

from ptpmon.local_interface import GlobalStatus, UdsServer

class _Dummy:
    """
    Client-facing simulator of ptpmond/ntpmon.

    It allows applications to connect to its UNIX domain socket and simulated
    TRS health status updates. The status can be set by the user via an
    interactive interface.
    """

    def __init__(self):
        self.logger = logging.getLogger('trsmond-dummy')
        self.global_status = GlobalStatus.PTP_BAD
        self.local_if = UdsServer(monitor=self, logger=self.logger)

    def run(self):
        """Simulator entry point"""
        print(cleandoc("""
        Supported commands:
          Set status: G|GOOD|PG|PTP_GOOD, B|BAD|PB|PTP_BAD, NG|NTP_GOOD, NB|NTP_BAD, T|TGL|TOGGLE
          Exit: Q|QUIT, EXIT, ^D
          """))

        status_name = {
            GlobalStatus.PTP_GOOD: 'PTP_GOOD',
            GlobalStatus.PTP_BAD : 'PTP_BAD',
            GlobalStatus.NTP_GOOD: 'NTP_GOOD',
            GlobalStatus.NTP_BAD : 'NTP_BAD',
        }

        self.local_if.start()
        try:
            while True:
                print('Status: {:>4}'.format(status_name[self.global_status]))
                line = input('--> ').upper()

                if line in ['G', 'GOOD', 'PG', 'PTP_GOOD']:
                    self.global_status = GlobalStatus.PTP_GOOD
                    self.local_if.notify(self.global_status, 'user cmd')
                elif line in ['B', 'BAD', 'PB', 'PTP_BAD']:
                    self.global_status = GlobalStatus.PTP_BAD
                    self.local_if.notify(self.global_status, 'user cmd')
                elif line in ['NG', 'NTP_GOOD']:
                    self.global_status = GlobalStatus.NTP_GOOD
                    self.local_if.notify(self.global_status, 'user cmd')
                elif line in ['NB', 'NTP_BAD']:
                    self.global_status = GlobalStatus.NTP_BAD
                    self.local_if.notify(self.global_status, 'user cmd')
                elif line in ['T', 'TGL', 'TOGGLE']:
                    if self.global_status in [GlobalStatus.PTP_GOOD, GlobalStatus.PTP_BAD]:
                        if self.global_status == GlobalStatus.PTP_GOOD:
                            self.global_status = GlobalStatus.PTP_BAD
                        elif self.global_status == GlobalStatus.PTP_BAD:
                            self.global_status = GlobalStatus.PTP_GOOD
                        self.local_if.notify(self.global_status, 'user cmd')
                    elif self.global_status in [GlobalStatus.NTP_GOOD, GlobalStatus.NTP_BAD]:
                        if self.global_status == GlobalStatus.NTP_GOOD:
                            self.global_status = GlobalStatus.NTP_BAD
                        elif self.global_status == GlobalStatus.NTP_BAD:
                            self.global_status = GlobalStatus.NTP_GOOD
                        self.local_if.notify(self.global_status, 'user cmd')
                elif line in ['Q', 'QUIT', 'EXIT']:
                    break
                elif line == '':
                    pass
                else:
                    print('Unknown command: {}'.format(line))
        except EOFError:    # CTRL-D
            pass
        self.local_if.stop()


def _sig_handler(signum, frame):
    """Make `input()` fail and unblock by closing stdin."""
    os.close(stdin.fileno())


def main():
    """Start the ptpmond/ntpmond simulator."""
    signal.signal(signal.SIGINT,  _sig_handler)
    signal.signal(signal.SIGTERM, _sig_handler)

    dummy = _Dummy()
    dummy.run()


if __name__ == '__main__':
    main()
