use std::ops::{Deref, DerefMut};
use crate::map::sources::baselayers::BASELAYER_OSM;
use crate::map::sources::{ActiveLayer, LayerId};
use crate::map::tiles::LayerManager;
use crate::ui::shell::footer::footer;
use crate::ui::shell::left_bar::left_bar;
use crate::ui::shell::right_bar::right_bar;
use crate::ui::shell::top_bar::top_bar;
use crate::ui::tokens::DESIGN_TOKENS;
use eframe::{Frame, Storage};
use egui::util::History;
use egui::Context;
use egui_demo_lib::{View, WidgetGallery};
use serde::{Deserialize, Serialize};
use walkers::{HttpTiles, MapMemory, Position, Tiles};

#[derive(Serialize, Deserialize)]
pub struct App {
    pub(crate) frame_time_history: History<f32>,
    add_layer_open: bool,
    selected_layer: Option<LayerId>,
    map_memory: MapMemory,
    layer_manager: LayerManager,
    position: Position,
}

impl App {
    pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
        DESIGN_TOKENS.apply(&cc.egui_ctx);
        egui_extras::install_image_loaders(&cc.egui_ctx);

        if let Some(storage) = cc.storage {
            if let Some(stored) = eframe::get_value(storage, eframe::APP_KEY) {
                let mut stored: Self = stored;
                stored.frame_time_history = History::new(1..100, 0.5);
                stored.layer_manager.ctx = Some(cc.egui_ctx.clone());

                return stored;
            }
        }

        let mut layer_manager = LayerManager::default();
        layer_manager.register_builtin_layers();
        layer_manager.active_layers.push(ActiveLayer {
            source_id: BASELAYER_OSM.source_id,
            layer_id: LayerId::new(),
            visible: true,
        });
        layer_manager.ctx = Some(cc.egui_ctx.clone());
        Self {
            frame_time_history: History::new(1..100, 0.5),
            add_layer_open: false,
            selected_layer: None,
            map_memory: MapMemory::default(),
            layer_manager,
            position: Position::new(35.227085, -80.843124),
        }
    }
}

impl eframe::App for App {
    fn save(&mut self, storage: &mut dyn Storage) {
        eframe::set_value(storage, eframe::APP_KEY, self);
    }

    fn update<'a>(&'a mut self, ctx: &'a Context, frame: &'a mut Frame) {
        if let Some(seconds) = frame.info().cpu_usage {
            self.frame_time_history.add(ctx.input(|i| i.time), seconds);
        }

        top_bar(ctx);
        footer(ctx, &self);
        left_bar(
            ctx,
            &mut self.add_layer_open,
            &mut self.layer_manager,
            &mut self.selected_layer,
        );
        //right_bar(ctx);

        egui::CentralPanel::default().show(ctx, |ui| {
            ui.add(walkers::Map::new(
                Some(&mut self.layer_manager),
                &mut self.map_memory,
                self.position
            ));
        });


    }
}
