mod toggle_switch;

use crate::toggle_switch::toggle;
use egui::Context;
use egui::{Align2, CollapsingHeader, Color32, Frame, UiBuilder, Window};
use std::collections::HashMap;
use std::env::var;
use walkers::sources::{Attribution, TileSource};
use walkers::{HttpOptions, HttpTiles, MapMemory, Position, TileId, Tiles};
use wxbox_common::TileRequestOptions;

pub struct WxboxApp {
    provider: HttpTiles,
    map_memory: MapMemory,
    tile_request_options: TileRequestOptions,

    rf_color: Color32,
}

pub struct DynamicUrlSource {
    pub url_query: String,
}
impl DynamicUrlSource {
    pub fn new_from(options: &TileRequestOptions) -> Self {
        Self {
            url_query: serde_json::to_string(options).unwrap(),
        }
    }
}
impl TileSource for DynamicUrlSource {
    fn tile_url(&self, tile_id: TileId) -> String {
        format!(
            "{}/{}/{}/{}.png?settings={}",
            env!("TILER_BASE_URL"),
            tile_id.zoom,
            tile_id.x,
            tile_id.y,
            self.url_query
        )
    }

    fn attribution(&self) -> Attribution {
        Attribution {
            text: "OpenStreetMap contributors, NOAA, wxbox",
            url: "https://copyright.wxbox.e3t.cc",
            logo_light: None,
            logo_dark: None,
        }
    }
}

impl WxboxApp {
    pub fn new(ctx: Context) -> Self {
        egui_extras::install_image_loaders(&ctx);

        let req_options = TileRequestOptions {
            baselayer: "osm".to_string(),

            data: "grib2/noaa_mrms_merged_composite_reflectivity_qc_CONUS".to_string(),
            data_transparency: 0.9,
            show_range_folded: false,
            range_folded_color: 0x8d00a0ff,
        };

        Self {
            provider: HttpTiles::with_options(
                DynamicUrlSource::new_from(&req_options),
                HttpOptions {
                    cache: if cfg!(target_arch = "wasm32") {
                        None
                    } else {
                        Some(".cache".into())
                    },
                    user_agent: None,
                },
                ctx.clone(),
            ),
            map_memory: MapMemory::default(),
            tile_request_options: req_options,
            rf_color: Color32::from_hex("#8d00a0ff").unwrap(),
        }
    }
}

impl eframe::App for WxboxApp {
    fn update(&mut self, ctx: &Context, frame: &mut eframe::Frame) {
        let rimless = Frame {
            fill: ctx.style().visuals.panel_fill,
            ..Default::default()
        };

        egui::CentralPanel::default()
            .frame(rimless)
            .show(ctx, |ui| {
                let Self {
                    provider,
                    map_memory,
                    tile_request_options,
                    rf_color
                } = self;

                let position = Position::from_lat_lon(44.967243, -103.771556);

                let tiles = provider;
                let attribution = tiles.attribution();

                let map = walkers::Map::new(Some(tiles), map_memory, position);

                ui.add(map);

                Window::new("Attribution")
                    .collapsible(false)
                    .resizable(false)
                    .title_bar(false)
                    .anchor(Align2::RIGHT_BOTTOM, [-10.0, -10.0])
                    .show(ui.ctx(), |ui| {
                        ui.horizontal(|ui| {
                            ui.hyperlink_to(attribution.text, attribution.url);
                        });
                        ui.horizontal(|ui| {
                            ui.label("wxbox is made with <3 by ");
                            ui.hyperlink_to("core", "https://coredoes.dev");
                            ui.label(" and ");
                            ui.hyperlink_to("tm85", "https://u8.lc");
                        });
                    });

                Window::new("wxbox")
                    .resizable(false)
                    .show(ui.ctx(), |ui| {
                        ui.heading("Welcome to wxbox!");
                        ui.label("We're glad you're here; Open up the Datasource panel to get started.");
                        ui.label("If you're using a mouse, you can click and drag to move around and Ctrl+Scroll to zoom.");
                        ui.label("On a touch-based device like a trackpad or touchscreen, you can tap/click and drag to move around and two-finger pinch to zoom.");
                        ui.label("You can close this window by clicking the arrow to the left of it's title.");
                    });

                let mut need_to_reset_for_next_frame = false;

                Window::new("Datasource")
                    .resizable(false)
                    .default_open(false)
                    .show(ui.ctx(), |ui| {
                        ui.collapsing("NOAA", |ui| {
                            ui.collapsing("Multi-Radar Multi-Sensor", |ui| {
                                for location in ["CONUS", "ALASKA", "CARIB", "GUAM", "HAWAII"] {
                                    ui.collapsing(location, |ui| {
                                        ui.collapsing("Composite Reflectivity", |ui| {
                                            if ui.radio_value(&mut tile_request_options.data, format!("grib2/noaa_mrms_merged_composite_reflectivity_qc_{}", location), "Composite Reflectivity (QCd)").changed() {
                                                need_to_reset_for_next_frame = true;
                                            }
                                        });

                                        if location == "CONUS" {
                                            ui.collapsing("RhoHV (Correlation Coefficient)", |ui| {
                                                if ui.radio_value(&mut tile_request_options.data, format!("grib2/noaa_mrms_merged_rhohv_3km_{}", location), "RhoHV @ 3.00 KM").changed() {
                                                    need_to_reset_for_next_frame = true;
                                                }
                                            });
                                        }
                                    });
                                }
                            });
                        });
                        ui.separator();
                        egui::Grid::new("dsconfig_grid")
                            .num_columns(2)
                            .spacing([40.0, 4.0])
                            .striped(true)
                            .show(ui, |ui| {
                                ui.label("Data opacity");
                                if ui.add(egui::Slider::new(&mut tile_request_options.data_transparency, 0.0..=1.0).suffix("%").custom_formatter(
                                    |u, v| {
                                        egui::emath::format_with_decimals_in_range(u * 100.0, v)
                                    }
                                )).changed() {
                                    need_to_reset_for_next_frame = true;
                                }
                                ui.end_row();

                                ui.label("Show range folded areas");
                                if ui.add(toggle(&mut tile_request_options.show_range_folded)).changed() {
                                    need_to_reset_for_next_frame = true;
                                }
                                ui.end_row();

                                ui.label("Range folded color");
                                if ui.color_edit_button_srgba(rf_color).changed() {
                                    let color = rf_color.to_array();
                                    let single_number = u32::from_be_bytes(color);
                                    tile_request_options.range_folded_color = single_number;
                                    need_to_reset_for_next_frame = true;
                                }
                            })
                    });

                if need_to_reset_for_next_frame {
                    *tiles = HttpTiles::with_options(
                        DynamicUrlSource::new_from(tile_request_options),
                        HttpOptions {
                            cache: if cfg!(target_arch = "wasm32") {
                                None
                            } else {
                                Some(".cache".into())
                            },
                            user_agent: None,
                        },
                        ctx.clone()
                    );
                }
            });
    }
}
