use crate::{style::*, InspectorModel, KeyCode};
use nodo::prelude::{ParameterDataType, ParameterValue};
use ratatui::{
    prelude::{Buffer, Constraint, Rect},
    style::{Color, Modifier, Style},
    text::Span,
    widgets::{Cell, Row, StatefulWidget, Table, Widget},
};
use std::{cell::RefCell, sync::Arc};

pub struct ConfigureController {
    pub model: Arc<RefCell<InspectorModel>>,
}

impl ConfigureController {
    pub fn on_key(&mut self, key: KeyCode) {
        match key {
            KeyCode::Down => self.select_next(),
            KeyCode::Up => self.select_previous(),
            KeyCode::PageDown => self.on_page_down(),
            KeyCode::PageUp => self.on_page_up(),
            KeyCode::Enter => {}
            _ => {}
        }
    }

    fn select_next(&mut self) {
        self.model.borrow_mut().config_table_state.select_next();
    }

    fn select_previous(&mut self) {
        self.model.borrow_mut().config_table_state.select_previous();
    }

    fn on_page_down(&mut self) {
        for _ in 0..10 {
            self.select_next()
        }
    }

    fn on_page_up(&mut self) {
        for _ in 0..10 {
            self.select_previous()
        }
    }
}

pub struct ConfigureView {
    pub model: Arc<RefCell<InspectorModel>>,
}

impl Widget for &ConfigureView {
    fn render(self, area: Rect, buf: &mut Buffer) {
        let mut model = self.model.borrow_mut();

        let entries: Vec<_> = model.tree.iter_parameters().collect();

        let combined_rows: Vec<_> = entries
            .iter()
            .map(|(_, _, n, p)| {
                Row::new(vec![
                    Cell::from(Span::styled(
                        n.info.node_name.clone(),
                        Style::default().fg(STYLE_COLOR_NODE_NAME),
                    )),
                    Cell::from(Span::styled(
                        p.name.clone(),
                        Style::default().fg(STYLE_COLOR_DETAIL_NAME),
                    )),
                    Cell::from(Span::styled(
                        format!(
                            "{}",
                            match p.dtype {
                                ParameterDataType::Bool => "bool",
                                ParameterDataType::Int64 => "i64",
                                ParameterDataType::Usize => "usize",
                                ParameterDataType::Float64 => "f64",
                                ParameterDataType::String => "String",
                                ParameterDataType::VecFloat64 => "Vec<f64>",
                            }
                        ),
                        Style::default().fg(STYLE_COLOR_TYPENAME),
                    )),
                    Cell::from(match p.is_mutable {
                        true => Span::styled("YES", Style::default().fg(STYLE_COLOR_VALUE_MUTABLE)),
                        false => Span::styled("NO", Style::default().fg(STYLE_COLOR_VALUE_DEFAULT)),
                    }),
                    Cell::from(Span::styled(
                        match &p.value {
                            ParameterValue::Bool(v) => format!("{v:?}"),
                            ParameterValue::Int64(v) => format!("{v:?}"),
                            ParameterValue::Usize(v) => format!("{v:?}"),
                            ParameterValue::Float64(v) => format!("{v:?}"),
                            ParameterValue::String(v) => format!("{v:?}"),
                            ParameterValue::VecFloat64(v) => format!("{v:?}"),
                        },
                        match p.is_mutable {
                            true => Style::default().fg(STYLE_COLOR_VALUE_MUTABLE),
                            false => Style::default().fg(STYLE_COLOR_VALUE_DEFAULT),
                        },
                    )),
                ])
            })
            .collect();

        // Create the combined table.
        let table = Table::new(
            combined_rows,
            &[
                Constraint::Fill(3),
                Constraint::Fill(3),
                Constraint::Fill(2),
                Constraint::Fill(1),
                Constraint::Fill(3),
            ],
        )
        .header(
            Row::new(vec![
                "Node".to_string(),
                "Parameter".into(),
                "Type".into(),
                "Mutable".into(),
                "Value".into(),
            ])
            .style(
                Style::default()
                    .add_modifier(Modifier::BOLD)
                    .add_modifier(Modifier::REVERSED),
            ),
        )
        .style(Style::new().fg(Color::White))
        .row_highlight_style(Style::new().add_modifier(Modifier::REVERSED));

        // Render the combined table.
        StatefulWidget::render(table, area, buf, &mut model.config_table_state);
    }
}
