use crate::{elements::Label, Table, WidgetBuilder};
use gtk4::{prelude::*, Align, Orientation, Widget};
use std::collections::HashMap;

impl WidgetBuilder {
    pub(super) fn create_table(&self, table: Table) -> Widget {
        let grid = gtk4::Grid::builder()
            .halign(Align::Center)
            .valign(Align::Center)
            .hexpand(true)
            .margin_end(6)
            .margin_start(6)
            .margin_top(6)
            .margin_bottom(6)
            .css_classes(["table"])
            .build();

        let mut skip_cells: HashMap<i32, i32> = HashMap::new();

        for (y, row) in table.rows.into_iter().enumerate() {
            let y = y as i32;

            let mut x_offset = 0;
            let mut row_width = 0;

            for (x, cell) in row.cells.into_iter().enumerate() {
                let x = x as i32;

                let item = self.build_element(cell.element, None, false);
                item.set_valign(Align::Center);
                item.set_halign(Align::Fill);
                item.set_margin_top(5);
                item.set_margin_bottom(5);
                item.set_margin_start(8);
                item.set_margin_end(8);
                let cell_container = libadwaita::Bin::builder()
                    .valign(Align::Fill)
                    .halign(Align::Fill)
                    .css_classes(["cell"])
                    .child(&item)
                    .build();

                if cell.is_header {
                    if let Some(text_view) = item.downcast_ref::<gtk4::TextView>() {
                        text_view.set_justification(gtk4::Justification::Center);
                    } else if let Some(label) = item.downcast_ref::<gtk4::Label>() {
                        label.set_xalign(0.5);
                    }
                }

                if skip_cells.contains_key(&x) {
                    x_offset += 1;
                }

                let x = x + x_offset;
                row_width = row_width.max(x + cell.width);
                let cell_width = cell.width.min(table.width - x);
                grid.attach(&cell_container, x, y, cell_width, cell.height);

                if cell.width > 1 {
                    x_offset += cell.width - 1;
                }

                if cell.height > 1 {
                    skip_cells.insert(x, cell.height);
                }
            }

            for x in row_width..table.width {
                let cell_container = libadwaita::Bin::builder()
                    .valign(Align::Fill)
                    .halign(Align::Fill)
                    .css_classes(["cell"])
                    .build();

                grid.attach(&cell_container, x, y, 1, 1);
            }

            skip_cells
                .iter_mut()
                .for_each(|(_column, row_count)| *row_count -= 1);
            skip_cells.retain(|_column, row_count| *row_count > 0);
        }

        if let Some(caption) = table.caption {
            let label = Label {
                text: caption.text.clone(),
                styles: vec!["title-2".to_string()],
                widgets: vec![],
                ..Default::default()
            };
            let label = self.create_label(label, false);
            label.set_halign(Align::Center);

            let box_ = gtk4::Box::builder()
                .orientation(Orientation::Vertical)
                .spacing(10)
                .margin_top(6)
                .margin_bottom(6)
                .build();
            box_.append(&label);
            box_.append(&grid);
            box_.upcast()
        } else {
            grid.upcast()
        }
    }
}
