#!/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's 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.

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

    def __init__(self):
        self.logger = logging.getLogger('ptpmond-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 simulator."""
    signal.signal(signal.SIGINT,  _sig_handler)
    signal.signal(signal.SIGTERM, _sig_handler)

    dummy = _Dummy()
    dummy.run()


if __name__ == '__main__':
    main()
