use std::io::{self, Write};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread;
use std::process;
use std::time::{Instant, Duration};
use serialport::SerialPort;
use crossterm::{
    event::{self, Event, KeyEvent, KeyCode},
    terminal::{disable_raw_mode, enable_raw_mode},
};

use crate::common;

fn send_takt_command(port: &mut Box<dyn SerialPort>, takt_number: u8) {
    let mut data = vec![0x01];
    
    match takt_number {
        1 => {
            data.push(0x50);
            data.extend_from_slice(&[0x11, 0x00]);
        },
        2 => {
            data.push(0x50);
            data.extend_from_slice(&[0x11, 0x01]);
        },
        3 => {
            data.push(0x50);
            data.extend_from_slice(&[0x12, 0x00]);
        },
        4 => {
            data.push(0x50);
            data.extend_from_slice(&[0x12, 0x01]);
        },
        5 => {
            data.push(0x50);
            data.extend_from_slice(&[0x12, 0x02]);
        },
        6 => {
            data.push(0x50);
            data.extend_from_slice(&[0x12, 0x03]);
        },
        7 => {
            data.push(0x50);
            data.extend_from_slice(&[0x12, 0x04]);
        },
        8 => {
            data.push(0x50);
            data.extend_from_slice(&[0x12, 0x05]);
        },
        9 => {
            data.push(0x50);
            data.extend_from_slice(&[0x12, 0x06]);
        },
        10 => {
            data.push(0x50);
            data.extend_from_slice(&[0x12, 0x07]);
        },
        11 => {
            data.push(0x50);
            data.extend_from_slice(&[0x12, 0x08]);
        },
        12 => {
            data.push(0x50);
            data.extend_from_slice(&[0x20, 0x00]);
        },
        13 => {
            data.push(0x50);
            data.extend_from_slice(&[0x20, 0x01]);
        },
        14 => {
            data.push(0x50);
            data.extend_from_slice(&[0x20, 0x02]);
        },
        15 => {
            data.push(0x50);
            data.extend_from_slice(&[0x20, 0x03]);
        },
        16 => {
            data.push(0x50);
            data.extend_from_slice(&[0x20, 0x04]);
        },
        17 => {
            data.push(0x50);
            data.extend_from_slice(&[0x20, 0x05]);
        },
        18 => {
            data.push(0x50);
            data.extend_from_slice(&[0x20, 0x06]);
        },
        19 => {
            data.push(0x50);
            data.extend_from_slice(&[0x20, 0x07]);
        },
        20 => {
            data.push(0x30);
            data.push(0x00);
        },
        21 => {
            data.push(0x30);
            data.push(0x01);
        },
        22 => {
            data.push(0x30);
            data.push(0x02);
        },
        23 => {
            data.push(0x30);
            data.push(0x03);
        },
        24 => {
            data.push(0x30);
            data.push(0x04);
        },
        25 => {
            data.push(0x30);
            data.push(0x05);
        },
        26 => {
            data.push(0x30);
            data.push(0x06);
        },
        _ => {
            println!("❌ Ошибка: неверный номер команды ТАКТ");
            return;
        }
    }
    
    let crc = common::calculate_crc16(&data);
    let mut final_data = data.clone();
    final_data.extend_from_slice(&crc.to_le_bytes());

    // Получаем имя порта (если возможно)
    let port_name = port.name().unwrap_or_else(|| String::from("Неизвестный порт"));
    
    let before_write = Instant::now();
    match port.write_all(&final_data) {
        Ok(_) => {
            let after_write = Instant::now();
            let elapsed_ms = after_write.duration_since(before_write).as_millis();
            println!("⏱️ Порт {}: время отправки данных {} мс",
                     port_name, elapsed_ms);
            
            println!("📤 Отправлена команда ТАКТ{}: {} | CRC: {:02X} {:02X}",
                     takt_number,
                     common::format_hex_output(&data),
                     crc & 0xFF, (crc >> 8) & 0xFF);
        },
        Err(e) => {
            println!("❌ Ошибка при отправке данных: {}", e);
        }
    }
}

fn show_menu() {
    println!("\n=== 📋 Меню команд ===");
    println!("1. Отправить HEX данные");
    println!("2. Отправить команды ТАКТ1...26");
    println!("3. Очистить экран");
    println!("4. Выход");
    print!("\nВыберите действие (1-4): ");
    io::stdout().flush().unwrap();
}

fn show_takt_menu() {
    println!("\n=== 📋 Меню команд ТАКТ ===");
    println!("Введите номер команды ТАКТ(1...26) или Меню (Esc)");
    print!("> ");
    io::stdout().flush().unwrap();
}

fn show_hex_menu() {
    println!("\n=== 📋 Меню отправки HEX данных ===");
    println!("Введите HEX данные (например: FF 00 AB) или Меню (Esc)");
    print!("> ");
    io::stdout().flush().unwrap();
}

fn handle_port_error(port_name: &str, e: serialport::Error) -> bool {
    println!("\n❌ Ошибка открытия порта {}: {}", port_name, e);
    println!("💡 Возможные причины:");
    println!("   - Порт используется другой программой");
    println!("   - Недостаточно прав доступа");
    println!("   - Устройство было отключено");

    loop {
        print!("\nПопробовать выбрать другой порт? (y/n): ");
        io::stdout().flush().unwrap();

        let mut input = String::new();
        if io::stdin().read_line(&mut input).is_err() {
            continue;
        }

        match input.trim().to_lowercase().as_str() {
            "y" => return true,
            "n" => {
                println!("\n👋 До свидания!");
                return false;
            }
            _ => println!("Пожалуйста, введите 'y' или 'n'"),
        }
    }
}

pub fn main() {
    // Set up Ctrl+C handler
    let running = Arc::new(AtomicBool::new(true));
    let r = running.clone();
    ctrlc::set_handler(move || {
        r.store(false, Ordering::Relaxed);
        println!("\n👋 Программа завершена пользователем (Ctrl+C)");
        process::exit(0);
    }).expect("Ошибка установки обработчика Ctrl+C");

    loop {
        if let Some(port_name) = common::select_port() {
            let mut port = match common::get_default_settings(&port_name, 9600)
                .timeout(Duration::from_millis(50))
                .open() {
                Ok(port) => port,
                Err(e) => {
                    if !handle_port_error(&port_name, e) {
                        return;
                    }
                    continue;
                }
            };

            // Получаем текущие настройки порта
            let baud_rate = port.baud_rate().unwrap_or(9600);
            let data_bits = port.data_bits().unwrap_or(serialport::DataBits::Eight);
            let stop_bits = port.stop_bits().unwrap_or(serialport::StopBits::One);
            let parity = port.parity().unwrap_or(serialport::Parity::None);
            let flow_control = port.flow_control().unwrap_or(serialport::FlowControl::None);

            println!("\n✅ Соединение установлено: Порт 📌: {} @ {} бод, {} бит данных, {} стоп-бит, {} четность, {} поток", 
                port_name, 
                baud_rate,
                match data_bits {
                    serialport::DataBits::Five => "5",
                    serialport::DataBits::Six => "6",
                    serialport::DataBits::Seven => "7",
                    serialport::DataBits::Eight => "8",
                },
                match stop_bits {
                    serialport::StopBits::One => "1",
                    serialport::StopBits::Two => "2",
                },
                match parity {
                    serialport::Parity::None => "нет",
                    serialport::Parity::Even => "четная",
                    serialport::Parity::Odd => "нечетная",
                },
                match flow_control {
                    serialport::FlowControl::None => "нет",
                    serialport::FlowControl::Hardware => "аппаратное",
                    serialport::FlowControl::Software => "программное",
                }
            );
            println!("\n🔄 Эмулятор готов к работе.");

            // Выводим текущие настройки порта
            println!("\n=== ТЕКУЩИЕ НАСТРОЙКИ ПОРТА ===");
            println!("Таймаут чтения/записи: {:?}", port.timeout());
            println!("Скорость: {:?} бод", port.baud_rate());
            println!("Биты данных: {:?}", port.data_bits());
            println!("Стоп-биты: {:?}", port.stop_bits());
            println!("Четность: {:?}", port.parity());
            println!("Управление потоком: {:?}", port.flow_control());
            println!("================================\n");
            io::stdout().flush().unwrap();

            let running_clone = running.clone();
            let mut port_clone = port.try_clone().expect("Failed to clone port");
            let pause_receiver = Arc::new(AtomicBool::new(false));
            let pause_receiver_clone = pause_receiver.clone();

            let receiver_thread = thread::spawn(move || {
                common::receive_data_with_pause(&mut port_clone, running_clone, pause_receiver_clone);
            });

            loop {
                if !running.load(Ordering::Relaxed) {
                    break;
                }

                show_menu();
                let mut input = String::new();
                if io::stdin().read_line(&mut input).is_err() {
                    continue;
                }

                match input.trim() {
                    "1" => {
                        // Pause receiver before entering HEX menu
                        pause_receiver.store(true, Ordering::Relaxed);
                        
                        // Enable raw mode for keyboard input
                        enable_raw_mode().expect("Failed to enable raw mode");
                        
                        // Show menu once at the start
                        show_hex_menu();
                        
                        let mut current_input = String::new();
                        let mut last_key_time = Instant::now();
                        let debounce_duration = Duration::from_millis(200);
                        
                        loop {
                            if !running.load(Ordering::Relaxed) {
                                disable_raw_mode().expect("Failed to disable raw mode");
                                break;
                            }
                            
                            if event::poll(std::time::Duration::from_millis(100)).unwrap() {
                                if let Event::Key(KeyEvent { code, .. }) = event::read().unwrap() {
                                    let now = Instant::now();
                                    match code {
                                        KeyCode::Esc => {
                                            disable_raw_mode().expect("Failed to disable raw mode");
                                            println!();
                                            break;
                                        }
                                        KeyCode::Enter => {
                                            if !current_input.is_empty() {
                                                // Clear the current line and move to next line
                                                print!("\x1B[2K\r\n");
                                                io::stdout().flush().unwrap();
                                                
                                                // Отправляем HEX данные
                                                common::send_hex_data(&mut port, &current_input);
                                                
                                                current_input.clear();
                                                println!();
                                                show_hex_menu();
                                            }
                                        }
                                        KeyCode::Char(c) => {
                                            if (c.is_ascii_hexdigit() || c == ' ') && 
                                               now.duration_since(last_key_time) > debounce_duration {
                                                current_input.push(c);
                                                last_key_time = now;
                                                // Clear the current line and show updated input
                                                print!("\x1B[2K\r> {}", current_input);
                                                io::stdout().flush().unwrap();
                                            }
                                        }
                                        KeyCode::Backspace => {
                                            if !current_input.is_empty() && 
                                               now.duration_since(last_key_time) > debounce_duration {
                                                current_input.pop();
                                                last_key_time = now;
                                                // Clear the current line and show updated input
                                                print!("\x1B[2K\r> {}", current_input);
                                                io::stdout().flush().unwrap();
                                            }
                                        }
                                        _ => {}
                                    }
                                }
                            }
                        }
                        
                        // Resume receiver after exiting HEX menu
                        pause_receiver.store(false, Ordering::Relaxed);
                    }
                    "2" => {
                        // Pause receiver before entering TAKT menu
                        pause_receiver.store(true, Ordering::Relaxed);
                        
                        // Enable raw mode for keyboard input
                        enable_raw_mode().expect("Failed to enable raw mode");
                        
                        // Show menu once at the start
                        show_takt_menu();
                        
                        let mut current_input = String::new();
                        let mut last_key_time = Instant::now();
                        let debounce_duration = Duration::from_millis(200);
                        
                        loop {
                            if !running.load(Ordering::Relaxed) {
                                disable_raw_mode().expect("Failed to disable raw mode");
                                break;
                            }
                            
                            if event::poll(std::time::Duration::from_millis(100)).unwrap() {
                                if let Event::Key(KeyEvent { code, .. }) = event::read().unwrap() {
                                    let now = Instant::now();
                                    match code {
                                        KeyCode::Esc => {
                                            disable_raw_mode().expect("Failed to disable raw mode");
                                            println!();
                                            break;
                                        }
                                        KeyCode::Enter => {
                                            if !current_input.is_empty() {
                                                // Clear the current line and move to next line
                                                print!("\x1B[2K\r\n");
                                                io::stdout().flush().unwrap();
                                                
                                                if let Ok(takt_number) = current_input.parse::<u8>() {
                                                    if takt_number >= 1 && takt_number <= 26 {
                                                        send_takt_command(&mut port, takt_number);
                                                        current_input.clear();
                                                        println!();
                                                        show_takt_menu();
                                                    } else {
                                                        println!("❌ Ошибка: номер команды ТАКТ должен быть от 1 до 26");
                                                        current_input.clear();
                                                        println!();
                                                        show_takt_menu();
                                                    }
                                                } else {
                                                    println!("❌ Ошибка: введите число от 1 до 26 или 'Esc' для выхода");
                                                    current_input.clear();
                                                    println!();
                                                    show_takt_menu();
                                                }
                                            }
                                        }
                                        KeyCode::Char(c) => {
                                            if c.is_ascii_digit() {
                                                if now.duration_since(last_key_time) > debounce_duration {
                                                    // Если это первая цифра или уже есть одна цифра
                                                    if current_input.is_empty() || current_input.len() == 1 {
                                                        // Если это вторая цифра, проверяем, что число не больше 26
                                                        if current_input.len() == 1 {
                                                            let first_digit = current_input.parse::<u8>().unwrap_or(0);
                                                            let second_digit = c.to_digit(10).unwrap_or(0) as u8;
                                                            let number = first_digit * 10 + second_digit;
                                                            if number > 26 {
                                                                continue;
                                                            }
                                                        }
                                                        current_input.push(c);
                                                        last_key_time = now;
                                                        // Clear the current line and show updated input
                                                        print!("\x1B[2K\r> {}", current_input);
                                                        io::stdout().flush().unwrap();
                                                    }
                                                }
                                            }
                                        }
                                        KeyCode::Backspace => {
                                            if !current_input.is_empty() {
                                                current_input.pop();
                                                // Clear the current line and show updated input
                                                print!("\x1B[2K\r> {}", current_input);
                                                io::stdout().flush().unwrap();
                                            }
                                        }
                                        _ => {}
                                    }
                                }
                            }
                        }
                        
                        // Resume receiver after exiting TAKT menu
                        pause_receiver.store(false, Ordering::Relaxed);
                    }
                    "3" => {
                        common::clear_screen();
                    }
                    "4" => {
                        println!("\n👋 До свидания!");
                        running.store(false, Ordering::Relaxed);
                        break;
                    }
                    _ => println!("⚠️ Неверный выбор. Пожалуйста, выберите 1-4"),
                }
            }

            if let Err(e) = receiver_thread.join() {
                eprintln!("Ошибка в потоке приема: {:?}", e);
            }
            break;
        } else {
            println!("❌ Выход: последовательный порт не выбран!");
            break;
        }
    }
} 