#!/usr/bin/env python3
# Copyright 2026 California Institute of Technology
#
# You should have received a copy of the licensing terms for this
# software included in the file “LICENSE” located in the top-level
# directory of this package. If you did not, you can view a copy at
# http://dcc.ligo.org/M1500244/LICENSE.txt

"""A small pcaspy IOC for the end-to-end test (see tests/e2e_ioc.rs and
tests/run_test_ioc.sh).  One of each kind of thing we display: a changing
value, a float, an enum with labels, a string, an int.

The process exits when stdin reaches EOF or reads a "quit" line, so the
test (or a shell pipeline) fully controls its lifetime.

Loopback binding and the port come from the standard portable-CAS
environment variables (EPICS_CAS_INTF_ADDR_LIST, EPICS_CA{,S}_SERVER_PORT),
set by the caller.
"""

import os
import sys
import threading
import time

from pcaspy import Driver, SimpleServer

PREFIX = "X1:"
PVDB = {
    "COUNT": {"type": "int", "value": 0},
    "VOLTS": {"type": "float", "prec": 2, "value": 3.25},
    "MODE": {"type": "enum", "enums": ["OFF", "ON", "AUTO"], "value": 1},
    "NAME": {"type": "string", "value": "hello world"},
    "INTVAL": {"type": "int", "value": 42},
}


class TestDriver(Driver):
    def __init__(self):
        super().__init__()
        threading.Thread(target=self._tick, daemon=True).start()

    def _tick(self):
        count = 0
        while True:
            time.sleep(0.5)
            count += 1
            self.setParam("COUNT", count)
            self.updatePVs()


def watch_stdin():
    for line in sys.stdin:
        if line.strip() == "quit":
            break
    # EOF or quit: hard-exit so the CAS threads can't keep us alive.
    os._exit(0)


def main():
    server = SimpleServer()
    server.createPV(PREFIX, PVDB)
    _driver = TestDriver()
    threading.Thread(target=watch_stdin, daemon=True).start()
    print("ready", flush=True)
    while True:
        server.process(0.1)


if __name__ == "__main__":
    main()
