"""
Simple CLI Example - Smart Card Command Tool

A command-line interface demonstrating how to use the API.py library
for sending APDU and escape commands to smart card readers.

Usage:
    python example_cli.py
"""

from API import list_readers, connect_to_reader, send_command, disconnect_reader, parse_command_string
from smartcard.util import toHexString
from smartcard.Exceptions import NoCardException

def list_available_readers():
    """List and display all available smart card readers."""
    readers = list_readers()
    
    if not readers:
        print("No smart card readers found.")
        return []
    
    print("Available readers:")
    for index, reader in enumerate(readers):
        print(f"{index + 1}: {reader}")
    
    return readers

def connect_to_reader_with_fallback(reader):
    """
    Connect to reader with automatic fallback logic.
    Tries standard mode (APDU) first, falls back to direct mode (escape) if no card.
    
    Returns:
        tuple: (connection, is_direct_mode, error_msg, context)
    """
    # Try standard connection first (APDU mode - requires card)
    connection, error_msg, _ = connect_to_reader(reader, mode='share')
    
    if connection:
        print("Connected in standard mode (APDU)")
        return connection, False, None, None
    
    # If connection failed due to no card, try direct mode (escape commands)
    if error_msg and "No card" in error_msg:
        print("No card detected, attempting direct mode...")
        hcard, error_msg, hcontext = connect_to_reader(reader, mode='direct')
        
        if hcard:
            print("Connected using Direct Mode (Escape commands)")
            return hcard, True, None, hcontext
        else:
            print(f"Direct Mode Failed: {error_msg}")
            return None, False, error_msg, None
    else:
        print(f"Standard Connection Failed: {error_msg}")
        return None, False, error_msg, None

def transmit_apdu(connection, command_hex):
    """Send an APDU command and display the response."""
    try:
        success, response, sw1, sw2, error_msg = send_command(
            connection,
            command_hex,
            mode='apdu'
        )
        
        if success:
            print(f"Response: {toHexString(response)}")
            print(f"Status words: {sw1:02X} {sw2:02X}")
        else:
            print(f"Transmit Failed: {error_msg}")
    except Exception as e:
        print(f"Transmit Failed: {str(e)}")

def transmit_escape(connection, command_hex):
    """Send an escape command and display the response."""
    try:
        command_bytes = parse_command_string(command_hex)
        success, response, error_msg = send_command(
            connection,
            command_bytes,
            mode='escape'
        )
        
        if success:
            if response and len(response) > 0:
                # Show first 50 bytes if response is long
                if len(response) > 50:
                    response_str = toHexString(response[:50])
                    print(f"Response ({len(response)} bytes): {response_str}...")
                else:
                    print(f"Response ({len(response)} bytes): {toHexString(response)}")
            else:
                print("Response: (empty)")
        else:
            print(f"Control Failed: {error_msg}")
    except Exception as e:
        print(f"Control Failed: {str(e)}")

def main():
    """Main interactive loop following apdu.py logic."""
    print("=" * 80)
    print("Smart Card Command Tool - CLI Example")
    print("=" * 80)
    print()
    
    while True:
        # List available readers
        pcsc_readers = list_available_readers()
        if not pcsc_readers:
            print("No readers available, exiting...")
            break
        
        # Prompt user to select reader or quit
        try:
            user_input = input("\nSelect the reader to connect or press 'q' to exit: ").strip()
        except KeyboardInterrupt:
            print("\n\nExiting...")
            break
        
        if user_input.lower() == 'q':
            break
        
        if not user_input:
            print("Please enter a number or 'q'")
            continue
        
        try:
            reader_index = int(user_input) - 1
            if 0 <= reader_index < len(pcsc_readers):
                selected_reader = pcsc_readers[reader_index]
                
                # Connect with automatic fallback
                connection, is_direct, error_msg, hcontext = connect_to_reader_with_fallback(selected_reader)
                
                if connection:
                    try:
                        if is_direct:
                            # Direct mode - escape commands
                            data = input("Enter the control data to transmit (in hex, e.g., 'E0 00 00 18 00'): ").strip()
                            if data:
                                transmit_escape(connection, data)
                        else:
                            # Standard mode - APDU commands
                            data = input("Enter the APDU to transmit (in hex, e.g., 'FF CA 00 00 00'): ").strip()
                            if data:
                                transmit_apdu(connection, data)
                    except KeyboardInterrupt:
                        print("\nCommand cancelled.")
                    except Exception as e:
                        print(f"Error: {str(e)}")
                    finally:
                        # Disconnect based on mode
                        if is_direct:
                            disconnect_reader(connection, hcontext)
                        else:
                            disconnect_reader(connection)
                else:
                    print("Connection failed")
            else:
                print("Invalid reader index")
        except ValueError:
            print("Please enter a valid number or 'q'")
        except KeyboardInterrupt:
            print("\n\nExiting...")
            break
    
    print("\nProgram completed.")

if __name__ == "__main__":
    main()
