#!/usr/bin/env python3
"""
Example script demonstrating how to use the EthLinxControl API.

This script provides a command-line interface to connect to a device,
read its information, settings, and stats, and apply new settings.
"""

import json
import argparse
import time
import os
import subprocess
from EthLinx_ControlAPI import EthLinxControl

def wait_for_device(ip_address, timeout=60):
    """Waits for the device to come back online by pinging it."""
    print(f"Waiting up to {timeout} seconds for device at {ip_address} to come back online...")
    start_time = time.monotonic()
    
    while time.monotonic() - start_time < timeout:
        # Use '-n 1' for Windows, '-c 1' for Linux/macOS
        command = ["ping", "-n", "1", "-w", "1000", ip_address]
        try:
            # Hide the console window for the ping command on Windows
            startupinfo = None
            if os.name == 'nt':
                startupinfo = subprocess.STARTUPINFO()
                startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            
            result = subprocess.run(command, capture_output=True, text=True, startupinfo=startupinfo)
            if result.returncode == 0 and ("TTL=" in result.stdout or "ttl=" in result.stdout):
                print(f"\n[SUCCESS] Device is back online.")
                return True
        except FileNotFoundError:
             print("\n[ERROR] Ping command not found. Cannot verify device readiness.")
             return False
        
        print(".", end="", flush=True)
        time.sleep(1)

    print(f"\n[FAIL] Timeout. Device did not come back online within {timeout} seconds.")
    return False

def main():
    """Main function to run the API demonstration."""
    parser = argparse.ArgumentParser(
        description="A command-line tool to interact with an EthLinx device using the EthLinxControl API.",
        formatter_class=argparse.RawTextHelpFormatter
    )
    parser.add_argument(
        "ip_address",
        nargs='?',
        default="192.168.222.1",
        help="IP address of the EthLinx device.\nDefaults to 192.168.222.1 if not provided."
    )
    parser.add_argument(
        "-v", "--verbose",
        action="store_true",
        help="Enable verbose debug output from the API."
    )
    args = parser.parse_args()

    print(f"--- Connecting to EthLinx device at {args.ip_address} ---")
    try:
        ethlinx = EthLinxControl(device_ip=args.ip_address, verbose=args.verbose)
    except Exception as e:
        print(f"Failed to initialize API client: {e}")
        return

    # 1. Get and print device info
    print("\n--- 1. Fetching Device Info ---")
    info = ethlinx.get_device_info()
    if info:
        print("Device Info received:")
        print(json.dumps(info, indent=2))
        channels = info.get("GeneralInfo", {}).get("Channels", 0)
        print(f"\nDevice reports it has {channels} serial channel(s).")
    else:
        print("\nFailed to get device info. Please check the IP address and device status. Halting script.")
        return

    # 2. Get and print current settings
    print("\n--- 2. Fetching Current Settings ---")
    settings = ethlinx.get_settings()
    if settings:
        print("Current settings received:")
        print(json.dumps(settings, indent=2))
    else:
        print("\nFailed to get settings. Halting script.")
        return

    # 3. Change and save settings for the first channel (if any exist)
    if channels > 0:
        bus_to_configure = "1"
        print(f"\n--- 3. Saving New Settings for Serial-{bus_to_configure} ---")
        success = ethlinx.save_settings(
            bus_id=bus_to_configure,
            label="Python API Test",
            baud_rate=115200,
            terminator=True,
            bias=False,
            data_bits=8, # Updated key name
            parity=0,    # 0=None, 1=Odd, 2=Even
            stop_bits=1
        )
        if success:
            print(f"Successfully applied new settings to Serial-{bus_to_configure}.")
            # 4. Verify by fetching settings again
            print("\n--- 4. Verifying by Fetching Settings After Change ---")
            new_settings = ethlinx.get_settings()
            if new_settings:
                print("New settings received:")
                print(json.dumps(new_settings, indent=2))
            else:
                print("Failed to fetch settings after the update for verification.")
        else:
            print(f"Failed to save new settings for Serial-{bus_to_configure}.")
    else:
        print("\n--- Skipping settings change (no channels found on device) ---")

    # 5. Get and print transfer stats
    print("\n--- 5. Fetching Transfer Stats ---")
    stats = ethlinx.get_stats()
    if stats:
        print("Current transfer stats received:")
        print(json.dumps(stats, indent=2))
    else:
        print("Failed to get transfer stats.")

    # 6. Clear stats and verify
    print("\n--- 6. Clearing Transfer Stats ---")
    if ethlinx.clear_stats():
        print("Waiting 2 seconds before re-fetching stats...")
        time.sleep(2)
        print("Re-fetching stats after clearing...")
        cleared_stats = ethlinx.get_stats()
        if cleared_stats:
            print("Stats after clearing:")
            print(json.dumps(cleared_stats, indent=2))
        else:
            print("Failed to re-fetch stats for verification.")
    else:
        print("Failed to send clear stats command.")

    # 7. Restart the device
    print("\n--- 7. Restarting Device ---")
    if ethlinx.restart_device():
        print("Restart command sent. The device will now reboot.")
        # 8. Wait for device to come back online
        print("\n--- 8. Waiting for Device to Reboot ---")
        wait_for_device(args.ip_address)
    else:
        print("Failed to send restart command.")

if __name__ == '__main__':
    main()

