"""
Example: Record from an LT device input

This example demonstrates how to:
    1. Connect to a given input source on an LT device.
    2. Verify that the source has a locked video signal.
    3. Create a worker to record the input in MP4 format.
    4. Save the recording to the current working directory.
    5. Capture keyboard events to control the recording:
       - space key : start/pause recording
       - any other key : stop recording

The recording is configured for a total duration of 20 seconds with file splits every 6 seconds.

Usage:
    record.exe -source <sourceURL>

Arguments:
    -source, -s    URL of a valid LT device input, for example:
                       lt310:/0/hdmi-in/0
                       lt310:/0/sdi-in/1

Note:
    This code is intended for demonstration purposes. For production use,
    ensure proper error handling and resource cleanup.

WARNING: on Ubuntu, this application should be run as admin

© 2025 Enciris Technologies. All rights reserved.
"""

import argparse
import os
import sys
import platform

# Platform-specific keyboard handling
if platform.system() == 'Windows':
    import msvcrt
else:
    import termios
    import tty
    import select

if __package__:
    from ... import lt
else:
    sys.path.append("../..")
    import lt


# Cross-platform keyboard input handling
class KeyboardInput:
    def __init__(self):
        self.is_windows = (platform.system() == 'Windows')
        if not self.is_windows:
            self.old_settings = termios.tcgetattr(sys.stdin)
            tty.setcbreak(sys.stdin.fileno())

    def kbhit(self):
        # Check if a key has been pressed
        if self.is_windows:
            return msvcrt.kbhit()
        else:
            return select.select([sys.stdin], [], [], 0)[0] != []

    def getch(self):
        # Get the pressed key
        if self.is_windows:
            return msvcrt.getch()
        else:
            return sys.stdin.read(1).encode()

    def __enter__(self):
        return self

    def __exit__(self, *args):
        if not self.is_windows:
            termios.tcsetattr(sys.stdin, termios.TCSADRAIN, self.old_settings)


# Command line arguments
def parse_args():
    class MyParser(argparse.ArgumentParser):
        def error(self, message):
            self.print_help()
            self.exit(2, f"\nError: {message}\n")

    parser = MyParser(
        description=(
            "This example verifies that the selected input source is active\n"
            "and starts a recording (mp4), capturing keyboard events to control the recording."
        ),
        formatter_class=argparse.RawTextHelpFormatter,
        add_help=False
    )

    group = parser.add_argument_group("Arguments")
    group.add_argument(
        "-source", "-s",
        required=True,
        metavar="URL",
        help=(
            "URL of a valid LT device input (e.g. lt310:/0/sdi-in/0)\n"
        )
    )

    return parser.parse_args()


def main():
    args = parse_args()
    sourceURL = args.source

    # Create LT client
    client = lt.Client()

    # -------------------------------------------------------------------------
    # Check if input selected is active
    # -------------------------------------------------------------------------
    try:
        input = client.Get(sourceURL)
        if input['video']['signal'] != 'locked':
            raise RuntimeError("input video source has no signal")
    except lt.SDKError as e:
        raise RuntimeError(f"error connecting to {sourceURL}: {e}") from e

    # -------------------------------------------------------------------------
    # Start recording from the selected input
    # -------------------------------------------------------------------------
    # Create worker
    workerURL = ""
    try:
        client.Post(sourceURL+"/file", lt.JSON({'media': "video/mp4", 'location': os.getcwd(), 'duration': 20, 'splitDuration': 6}))
    except lt.RedirectError as e:
        workerURL = e.location
    except lt.SDKError as e:
        raise RuntimeError("server did not return a redirect")

    # Loop
    is_paused = False
    recordLength = 0
    print("Press SPACE to start/pause recording, any other key to stop.\n")
    # Loop with keyboard handling
    with KeyboardInput() as kb:
        while True:
            try:
                # Check for keyboard input
                if kb.kbhit():
                    key = kb.getch()

                    # Space key to pause/resume
                    if key == b' ':
                        if is_paused:
                            # Resume recording
                            client.Post(workerURL+"/start", lt.JSON({}))
                            is_paused = False
                        else:
                            # Pause recording
                            client.Post(workerURL+"/pause", lt.JSON({}))
                            is_paused = True
                    else:
                        # Any other key stops recording
                        client.Post(workerURL+"/stop", lt.JSON({}))
                        print("\nRecording stopped by user.")
                        break

                # Fetch worker update
                worker = client.Get(workerURL)

                # Process all packets (display only video packet info)
                for packet in worker['packets']:
                    if packet['media'].split('/')[0] == 'video':
                        meta = packet['meta']
                        info = '{:s} {:s} {:d}x{:d} {:d} bytes'.format(sourceURL, worker['name'], meta['size'][0], meta['size'][1], worker['length'] - recordLength)
                        print('\r'+info, end='')

                # When status is "completed", the current file is closed (either due to split or worker stopped)
                # Save the total recording size and print a new line for the next file
                if worker['status'] == 'completed':
                    recordLength = worker['length']
                    print()


            except lt.SDKError as e:
                if str(e) == lt.ErrEOF:
                    print("\nRecording saved successfully.")
                else:
                    print(f"\nfailed to get worker: {e}")
                break

            except Exception as e:
                print(f"\nAn error occurred: {e}")
                break

            except KeyboardInterrupt:
                print("\nKeyboardInterrupt has been caught.")
                break


if __name__ == "__main__":
    main()
