use crate::solar_system::SolarSystem;
use crate::fleet::FleetsManager;
use crate::ui::contact::MapContact;

pub struct ContactsListWidget<'f>
{
    contacts: Vec<(MapContact, &'f String)>,
    selected: &'f mut Option<MapContact>
}

pub struct FocusedContactWidget<'f>
{
    contact: Option<MapContact>,
    star_system: &'f SolarSystem,
    fleets_man: &'f FleetsManager
}

impl<'f> ContactsListWidget<'f>
{
    pub fn new(
        selected: &'f mut Option<MapContact>,
        star_system: &'f SolarSystem,
        fleets_man: &'f FleetsManager)
    -> Self {
        let system_fleets = fleets_man.all_in_system(star_system.id());
        let system_bodies = star_system.bodies();

        let mut contacts = system_fleets.iter().map(|id| {
            let fleet = fleets_man.fleet(*id);
            (MapContact::from_fleet(*id), fleet.unwrap().name())
        }).collect::<Vec<_>>();
        contacts.extend(system_bodies.iter().map(|body| {
            (MapContact::from_body(body.id()), body.name())
        }));

        Self {
            contacts: contacts,
            selected
        }
    }

    pub fn show_ui(
        mut self,
        ui: &mut egui::Ui)
    -> egui::InnerResponse<Option<MapContact>>
    {
        self.show_entries_box(ui)
    }

    fn show_entries_box(
        &mut self,
        ui: &mut egui::Ui)
    -> egui::InnerResponse<Option<MapContact>>
    {
        let mut ret = None;
        egui::Frame::default()
            .stroke(egui::Stroke::NONE)
            .fill(egui::Color32::from_rgb(48, 48, 48))
            .outer_margin(egui::Margin::same(4))
            .inner_margin(egui::Margin::same(4))
        .show(ui, |frame| {
            frame.take_available_width();
            frame.set_max_height(frame.available_height() / 2.0);

            frame.vertical(|vertical| {
                let mut table = egui_extras::TableBuilder::new(vertical)
                    .striped(true)
                    .resizable(false)
                    .auto_shrink(false)
                    .column(egui_extras::Column::remainder())
                    .body(
                |body| {
                    let row_height = 20.0;
                    body.rows(row_height, self.contacts.len(), |mut row| {
                        let resp = self.show_contact(&mut row);
                        if resp.is_some() {
                            ret = resp;
                        }
                    });
                });
            });
            ret
        })
    }

    fn show_contact(
        &mut self,
        row: &mut egui_extras::TableRow)
    -> Option<MapContact>
    {
        let contact = &self.contacts[row.index()];
        let selected = self.selected.is_some_and(|sel| { sel == contact.0 });

        let mut ret = None;
        row.col(|col| {
            let resp = col.selectable_label(selected, contact.1);

            if resp.double_clicked() {
                ret = Some(contact.0);
            }else if resp.clicked() {
                *self.selected = match selected {
                    true => None,
                    false => Some(contact.0)
                };
            }
        });
        ret
    }
}

impl<'f> FocusedContactWidget<'f>
{
    pub fn new(
        contact: Option<MapContact>,
        star_system: &'f SolarSystem,
        fleets_man: &'f FleetsManager)
    -> Self {
        Self {
            contact,
            star_system,
            fleets_man
        }
    }
}

impl egui::Widget for FocusedContactWidget<'_>
{
    fn ui(self, ui: &mut egui::Ui) -> egui::Response {
        ui.vertical(|vertical| {
            vertical.label("Focused contact");
            vertical.shrink_width_to_current();
            egui::Frame::new()
                .fill(egui::Color32::from_gray(48))
                .stroke(egui::Stroke::NONE)
                .inner_margin(egui::Margin::same(2))
                .show(vertical,
            |frame| {
                frame.take_available_width();
                match self.contact {
                    Some(contact) => frame.label(contact.name(self.star_system, self.fleets_man)),
                    None => frame.label("None")
                }
            }).inner
        }).inner
    }
}
