# SPDX-FileCopyrightText: 2022 CERN (home.cern)
# SPDX-License-Identifier: TODO

from PyWrtd import PyWrtd
from PyAdcLib import *

import time

class FmcAdc100m(PyFmcAdc100m14b4ch):
    def __init__(self, adc_id):
        PyFmcAdc100m14b4ch.__init__(self, adc_id)
        for ch in range(4):
            conf = PyAdcConf(PyAdcConf.ADC_CONF_TYPE_CHN, ch)
            conf.value_set(PyAdcConf.ADC_CONF_CHN_RANGE,
                           self.ADC_CONF_100M14B4CHA_CHN_RANGE_10V)
            conf.value_set(PyAdcConf.ADC_CONF_CHN_TERMINATION, 1)
            conf.value_set(PyAdcConf.ADC_CONF_CHN_OFFSET, 0)
            conf.value_set(PyAdcConf.ADC_CONF_CHN_SATURATION, 0x7FFF)
            self.apply_config(conf, 0)
        self.disable_triggers()

    def disable_triggers(self):
        for ch in range(4):
            conf = PyAdcConf(PyAdcConf.ADC_CONF_TYPE_TRG_THR, ch)
            conf.value_set(PyAdcConf.ADC_CONF_TRG_THR_ENABLE, 0)
            self.apply_config(conf, 0)
        conf = PyAdcConf(PyAdcConf.ADC_CONF_TYPE_TRG_EXT, 0)
        conf.value_set(PyAdcConf.ADC_CONF_TRG_EXT_ENABLE, 0)
        self.apply_config(conf, 0)

    def enable_ext_trigger(self):
        conf = PyAdcConf(PyAdcConf.ADC_CONF_TYPE_TRG_EXT, 0)
        conf.value_set(PyAdcConf.ADC_CONF_TRG_EXT_ENABLE, 1)
        self.apply_config(conf, 0)

    def enable_int_trigger(self, ch):
        conf = PyAdcConf(PyAdcConf.ADC_CONF_TYPE_TRG_THR, ch)
        conf.value_set(PyAdcConf.ADC_CONF_TRG_THR_THRESHOLD, 2000)
        conf.value_set(PyAdcConf.ADC_CONF_TRG_THR_ENABLE, 1)
        self.apply_config(conf, 0)

    def start_acquisition(self, pre, post, nshot=1):
        conf = PyAdcConf(PyAdcConf.ADC_CONF_TYPE_ACQ, 0)
        conf.value_set(PyAdcConf.ADC_CONF_ACQ_PRE_SAMP, pre)
        conf.value_set(PyAdcConf.ADC_CONF_ACQ_POST_SAMP, post)
        conf.value_set(PyAdcConf.ADC_CONF_ACQ_N_SHOTS, nshot)
        self.apply_config(conf, 0)
        self.acq_start(PyFmcAdc100m14b4ch.ADC_F_FLUSH, timeval(0,0))

    def acquisition_complete(self):
        try:
            self.acq_poll(0, timeval(1,0))
            return True
        except OSError:
            return False

class WrtdTestNode(PyWrtd):
    def __init__(self, node_id, fw_name):
        PyWrtd.__init__(self, node_id)
        self.node_id = node_id
        self.expected_fw_name = fw_name

        self.disable_all_alarms()
        self.remove_all_alarms()
        self.disable_all_rules()
        self.remove_all_rules()
        self.set_attr_bool(self.WRTD_GLOBAL_REP_CAP_ID,
                           self.WRTD_ATTR_EVENT_LOG_ENABLED,
                           False)
        self.clear_event_log_entries()
        self.set_attr_bool(self.WRTD_GLOBAL_REP_CAP_ID,
                           self.WRTD_ATTR_EVENT_LOG_ENABLED,
                           True)

    def set_attr_tstamp(self, rep_cap_id, id,
                        seconds = 0, ns = 0, frac = 0):
        sec_normalised = seconds
        ns_normalised = ns
        while (ns_normalised >= 1000000000):
            ns_normalised  -= 1000000000
            sec_normalised += 1
        while (ns_normalised < 0):
            ns_normalised  += 1000000000
            sec_normalised -= 1
        PyWrtd.set_attr_tstamp(self, rep_cap_id, id,
                               sec_normalised, ns_normalised, frac)

    def add_rule_enabled(self, name, src, dst, ns_delay = 0, repeat = 0):
        self.add_rule(name)
        self.set_attr_tstamp(name, self.WRTD_ATTR_RULE_DELAY, ns = ns_delay)
        self.set_attr_string(name, self.WRTD_ATTR_RULE_SOURCE, src)
        self.set_attr_string(name, self.WRTD_ATTR_RULE_DESTINATION, dst)
        self.set_attr_int32(name, self.WRTD_ATTR_RULE_REPEAT_COUNT, repeat)
        self.set_attr_bool(name, self.WRTD_ATTR_RULE_ENABLED, True)

    def check_log_entry(self, pattern, timeout = 1.0):
        remaining = timeout
        while self.get_attr_bool(self.WRTD_GLOBAL_REP_CAP_ID,
                                 self.WRTD_ATTR_EVENT_LOG_EMPTY):
            assert remaining > 0
            time.sleep(0.1)
            remaining -= 0.1
        entry = self.get_next_event_log_entry()
        log_fields = [ x.strip() for x in entry.split('|')]
        assert len(log_fields) == 6
        log = dict()
        log['id']           = log_fields[0].lstrip('Id:')
        log['seq']          = log_fields[1].lstrip('Seq:')
        log['log_tstamp']   = log_fields[2]
        log['event_tstamp'] = log_fields[3]
        log['log_type']     = log_fields[4]
        log['log_reason']   = log_fields[5]

        for key in pattern:
            assert key in log
            assert log[key] == pattern[key]

        return log
