import React, { useState, KeyboardEvent, useEffect } from 'react';

type InputMode = 'ASCII' | 'HEX';

interface InputBarProps {
  onSend: (data: Uint8Array) => void;
  disabled: boolean;
}

const InputBar: React.FC<InputBarProps> = ({ onSend, disabled }) => {
  const [text, setText] = useState('');
  const [stx, setStx] = useState('');
  const [etx, setEtx] = useState('');
  const [mode, setMode] = useState<InputMode>('ASCII');
  
  // Error states for validation
  const [errors, setErrors] = useState({ stx: false, text: false, etx: false });

  // Command History State
  const [history, setHistory] = useState<string[]>([]);
  const [historyIndex, setHistoryIndex] = useState<number>(-1);

  // Clear errors when mode changes
  useEffect(() => {
    setErrors({ stx: false, text: false, etx: false });
  }, [mode]);

  const isValidHex = (str: string): boolean => {
    // Allow empty string, hex digits, and spaces.
    // Checks if there is any character that is NOT 0-9, a-f, A-F, or whitespace
    return !/[^0-9A-Fa-f\s]/.test(str);
  };

  const parseString = (str: string, mode: InputMode): Uint8Array => {
    if (mode === 'HEX') {
        // Remove spaces and non-hex characters (cleaning is still done for safe parsing)
        const clean = str.replace(/[^0-9A-Fa-f]/g, '');
        if (clean.length === 0) return new Uint8Array(0);
        
        const bytes = new Uint8Array(Math.ceil(clean.length / 2));
        for (let i = 0; i < bytes.length; i++) {
            const hexPair = clean.slice(i * 2, i * 2 + 2).padEnd(2, '0'); 
            bytes[i] = parseInt(hexPair, 16);
        }
        return bytes;
    } else {
        // ASCII Mode with Escape Sequence Parsing
        const unescaped = str
            .replace(/\\r/g, '\r')
            .replace(/\\n/g, '\n')
            .replace(/\\t/g, '\t')
            .replace(/\\0/g, '\0')
            .replace(/\\x([0-9A-Fa-f]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)));
        
        return new TextEncoder().encode(unescaped);
    }
  };

  const handleSend = () => {
    // Validation for HEX mode
    if (mode === 'HEX') {
        const stxValid = isValidHex(stx);
        const textValid = isValidHex(text);
        const etxValid = isValidHex(etx);

        setErrors({
            stx: !stxValid,
            text: !textValid,
            etx: !etxValid
        });

        if (!stxValid || !textValid || !etxValid) {
            return; // Stop sending if validation fails
        }
    }

    try {
        const stxBytes = stx ? parseString(stx, mode) : new Uint8Array(0);
        const bodyBytes = text ? parseString(text, mode) : new Uint8Array(0);
        const etxBytes = etx ? parseString(etx, mode) : new Uint8Array(0);
        
        if (stxBytes.length === 0 && bodyBytes.length === 0 && etxBytes.length === 0) return;

        const totalLength = stxBytes.length + bodyBytes.length + etxBytes.length;
        const result = new Uint8Array(totalLength);
        
        result.set(stxBytes, 0);
        result.set(bodyBytes, stxBytes.length);
        result.set(etxBytes, stxBytes.length + bodyBytes.length);

        onSend(result);
        
        // Add to history
        if (text.trim() !== '') {
            setHistory(prev => {
                const newHistory = [...prev];
                if (newHistory[newHistory.length - 1] !== text) {
                    newHistory.push(text);
                }
                if (newHistory.length > 50) return newHistory.slice(-50);
                return newHistory;
            });
        }
        
        setText('');
        setHistoryIndex(-1);

    } catch (e) {
        console.error("Parse error", e);
        alert("Error parsing input data.");
    }
  };

  const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'Enter') {
      handleSend();
    } else if (e.key === 'ArrowUp') {
        e.preventDefault();
        if (history.length === 0) return;

        setHistoryIndex(prevIndex => {
            const newIndex = prevIndex === -1 ? history.length - 1 : Math.max(0, prevIndex - 1);
            setText(history[newIndex]);
            // Clear text error when recalling history
            setErrors(prev => ({ ...prev, text: false }));
            return newIndex;
        });
    } else if (e.key === 'ArrowDown') {
        e.preventDefault();
        if (history.length === 0 || historyIndex === -1) return;

        setHistoryIndex(prevIndex => {
            if (prevIndex >= history.length - 1) {
                setText('');
                return -1;
            } else {
                const newIndex = prevIndex + 1;
                setText(history[newIndex]);
                // Clear text error when recalling history
                setErrors(prev => ({ ...prev, text: false }));
                return newIndex;
            }
        });
    }
  };

  const getBorderClass = (hasError: boolean) => {
    return hasError 
        ? "border-red-500 focus:ring-red-500 text-red-300 placeholder-red-300/50" 
        : "border-gray-700 focus:ring-indigo-500 text-white placeholder-gray-700";
  };

  return (
    <div className="flex flex-col md:flex-row items-center gap-2 p-3 bg-gray-850 border-t border-gray-800">
      <div className="flex items-center gap-2 w-full md:w-auto">
        {/* Mode Toggle */}
        <div className="flex bg-gray-900 rounded border border-gray-700">
            <button
                onClick={() => setMode('ASCII')}
                className={`px-2 py-1 text-[10px] font-bold rounded-l transition-all ${
                mode === 'ASCII' ? 'bg-indigo-600 text-white' : 'text-gray-400 hover:text-white'
                }`}
            >
                ASC
            </button>
            <button
                onClick={() => setMode('HEX')}
                className={`px-2 py-1 text-[10px] font-bold rounded-r transition-all ${
                mode === 'HEX' ? 'bg-indigo-600 text-white' : 'text-gray-400 hover:text-white'
                }`}
            >
                HEX
            </button>
        </div>
      </div>

      <div className="flex flex-1 items-center gap-2 w-full">
        {/* STX Input */}
        <input
            type="text"
            value={stx}
            onChange={(e) => {
                setStx(e.target.value);
                if (errors.stx) setErrors(prev => ({ ...prev, stx: false }));
            }}
            disabled={disabled}
            placeholder="STX"
            className={`w-14 bg-gray-900 text-xs border rounded px-2 py-2 focus:ring-1 outline-none text-center font-mono transition-colors ${
                errors.stx 
                ? "border-red-500 focus:ring-red-500 text-red-400 placeholder-red-400/50" 
                : "border-gray-700 focus:ring-indigo-500 text-amber-200 placeholder-gray-700"
            }`}
            title="Start Byte (e.g. \x02 or 02)"
        />

        {/* Main Input */}
        <input
            type="text"
            value={text}
            onChange={(e) => {
                setText(e.target.value);
                setHistoryIndex(-1);
                if (errors.text) setErrors(prev => ({ ...prev, text: false }));
            }}
            onKeyDown={handleKeyDown}
            disabled={disabled}
            placeholder={disabled ? "Disconnected..." : (mode === 'HEX' ? (errors.text ? "Invalid HEX!" : "AA BB CC...") : "Type message (supports \\r\\n)...")}
            className={`flex-1 bg-gray-900 text-sm border rounded px-3 py-2 focus:ring-2 outline-none disabled:opacity-50 font-mono transition-colors ${getBorderClass(errors.text)}`}
        />

        {/* ETX Input */}
        <input
            type="text"
            value={etx}
            onChange={(e) => {
                setEtx(e.target.value);
                if (errors.etx) setErrors(prev => ({ ...prev, etx: false }));
            }}
            disabled={disabled}
            placeholder="ETX"
            className={`w-14 bg-gray-900 text-xs border rounded px-2 py-2 focus:ring-1 outline-none text-center font-mono transition-colors ${
                errors.etx
                ? "border-red-500 focus:ring-red-500 text-red-400 placeholder-red-400/50" 
                : "border-gray-700 focus:ring-indigo-500 text-amber-200 placeholder-gray-700"
            }`}
            title="End Byte (e.g. \r\n or 0D 0A)"
        />

        <button
            onClick={handleSend}
            disabled={disabled}
            className={`text-white text-xs font-bold px-4 py-2 rounded transition-colors uppercase tracking-wider h-full ${
                (errors.stx || errors.text || errors.etx)
                ? "bg-red-600 hover:bg-red-500"
                : "bg-indigo-600 hover:bg-indigo-500 disabled:bg-gray-700"
            }`}
        >
            {(errors.stx || errors.text || errors.etx) ? 'Fix' : 'Send'}
        </button>
      </div>
    </div>
  );
};

export default InputBar;