// Copyright Marcus Del Favero 2025
// Licensed under the GNU AGPLv3 with an exception, see `README.md` for details
use egui::{FontId, RichText, TextEdit, Style, Color32, Ui, Label, Button, Response};

pub trait FontSize { // Makes my job easier when setting the font size
	fn font_size(self, size: f32) -> Self;
}

impl FontSize for RichText {
	fn font_size(self, size: f32) -> RichText {
		self.font(FontId::proportional(size))
	}
}

impl<'a> FontSize for TextEdit<'a> {
	fn font_size(self, size: f32) -> TextEdit<'a> {
		self.font(FontId::proportional(size))
	}
}

pub(super) const BACKGROUND: Color32 = Color32::from_gray(0x17);

pub const LABEL_SIZE: f32 = 14.0;

pub const H1_SIZE: f32 = 60.0;
pub const H2_SIZE: f32 = 30.0;
pub const H3_SIZE: f32 = 20.0;
pub const H4_SIZE: f32 = 15.0;

pub const SCORE_H1_SIZE: f32 = 20.0;
pub const SCORE_H2_SIZE: f32 = 14.0;

pub const H1_COLOUR: Color32 = Color32::from_rgb(0xff, 0x5f, 0x4f);
pub const H2_COLOUR: Color32 = Color32::from_rgb(0xff, 0x7f, 0x6f);
pub const H3_COLOUR: Color32 = Color32::from_rgb(0xff, 0x9f, 0x8f);

pub const B1_SIZE: f32 = 36.0;
pub const B2_SIZE: f32 = 24.0;

pub const LABEL_COLOUR: Color32 = Color32::from_gray(0xdf);
pub const BUTTON_COLOUR: Color32 = Color32::from_gray(0xe7);

pub const STYLE_SETTINGS_BIND_BUTTON: f32 = 12.0;

pub trait UiExt {
	fn h1<'a>(&'a mut self, text: &'a str) -> HeaderBuilder<'a>;
	fn h2<'a>(&'a mut self, text: &'a str) -> HeaderBuilder<'a>;
	fn h3<'a>(&'a mut self, text: &'a str) -> HeaderBuilder<'a>;

	fn b1(&mut self, s: &str) -> Response;
	fn b2(&mut self, s: &str) -> Response;

	fn b1_enabled(&mut self, s: &str, enabled: bool) -> Response;
	fn b2_enabled(&mut self, s: &str, enabled: bool) -> Response;

	fn b_back(&mut self) -> Response;
}

impl UiExt for Ui {
	fn h1<'a>(&'a mut self, text: &'a str) -> HeaderBuilder<'a> { HeaderBuilder::new(self, text, H1_SIZE, H1_COLOUR) }
	fn h2<'a>(&'a mut self, text: &'a str) -> HeaderBuilder<'a> { HeaderBuilder::new(self, text, H2_SIZE, H2_COLOUR) }
	fn h3<'a>(&'a mut self, text: &'a str) -> HeaderBuilder<'a> { HeaderBuilder::new(self, text, H3_SIZE, H3_COLOUR) }

	fn b1(&mut self, s: &str) -> Response { self.b1_enabled(s, true) }
	fn b2(&mut self, s: &str) -> Response { self.b2_enabled(s, true) }

	fn b1_enabled(&mut self, s: &str, enabled: bool) -> Response { button(self, s, B1_SIZE, enabled) }
	fn b2_enabled(&mut self, s: &str, enabled: bool) -> Response { button(self, s, B2_SIZE, enabled) }

	fn b_back(&mut self) -> Response {
		self.add_space(45.0);
		self.b2("Back")
	}
}

#[must_use = "Need to call `.add()` to add the header."]
pub struct HeaderBuilder<'a> {
	ui: &'a mut Ui,
	text: &'a str,
	font_size: f32,
	colour: Color32,
	padding_top: bool,
	padding_bottom: bool,
	selectable: bool,
}

impl<'a> HeaderBuilder<'a> {
	fn new(ui: &'a mut Ui, text: &'a str, font_size: f32, colour: Color32) -> HeaderBuilder<'a> {
		HeaderBuilder { ui, text, font_size, colour, padding_top: true, padding_bottom: true, selectable: false }
	}

	pub fn selectable(mut self) -> Self {
		self.selectable = true;
		self
	}

	pub fn no_padding(mut self) -> Self {
		self.padding_top = false;
		self.padding_bottom = false;
		self
	}

	pub fn no_bottom_padding(mut self) -> Self {
		self.padding_bottom = false;
		self
	}

	pub fn add(self) {
		if self.padding_top { self.ui.add_space(self.font_size); }
		self.ui.add(Label::new(RichText::new(self.text).font_size(self.font_size).color(self.colour)).selectable(self.selectable));
		if self.padding_bottom { self.ui.add_space(self.font_size / 2.0); }
	}
}

fn button(ui: &mut Ui, s: &str, font_size: f32, enabled: bool) -> Response {
	ui.add_enabled(enabled, Button::new(RichText::new(s).font_size(font_size).color(BUTTON_COLOUR)))
}

pub(super) const WIDGET_BACKGROUND: Color32 = Color32::from_gray(0x3f);
pub(super) const WIDGET_HOVERED_BACKGROUND: Color32 = Color32::from_rgb(0x5f, 0x2f, 0x2f);
pub(super) const WIDGET_ACTIVE_BACKGROUND: Color32 = Color32::from_rgb(0x7f, 0x2f, 0x2f);

pub(super) const WIDGET_STROKE: Color32 = Color32::from_gray(0x4f);
pub(super) const WIDGET_HOVERED_STROKE: Color32 = Color32::from_rgb(0xaf, 0x4f, 0x4f);
pub(super) const WIDGET_ACTIVE_STROKE: Color32 = Color32::from_rgb(0xcf, 0x4f, 0x4f);

/*
 * Can make lighter to be consistent with the website, but there needs to be
 * a way to distinguish strong text, as egui doesn't support easily applying
 * bold. Could make this strong text a different colour but that won't look
 * as good.
 *
 * Also the text overall is slightly bolder than the normal text on the
 * website, so it being slightly darker shouldn't be a problem.
 */
const WIDGET_FOREGROUND_DARK: Color32 = Color32::from_gray(0xaf);
const WIDGET_FOREGROUND_NORMAL: Color32 = Color32::from_gray(0xcf);
const WIDGET_FOREGROUND_LIGHT: Color32 = LABEL_COLOUR;

const SELECTION: Color32 = Color32::from_rgb(0x6f, 0x33, 0x33);
const SELECTION_BRIGHT: Color32 = Color32::from_rgb(0xff, 0xcf, 0xcf);

const LINK_COLOUR: Color32 = Color32::from_rgb(0xff, 0xff, 0x8f);

pub(super) fn set(style: &mut Style) {
	style.interaction.tooltip_delay = 0.0;
	style.interaction.tooltip_grace_time = 0.25;
	style.interaction.show_tooltips_only_when_still = false;

	style.visuals.widgets.noninteractive.bg_fill = BACKGROUND;
	style.visuals.widgets.noninteractive.weak_bg_fill = BACKGROUND;
	style.visuals.widgets.noninteractive.bg_stroke.color = WIDGET_STROKE;
	style.visuals.widgets.noninteractive.fg_stroke.color = WIDGET_FOREGROUND_DARK;

	style.visuals.widgets.inactive.bg_fill = WIDGET_BACKGROUND;
	style.visuals.widgets.inactive.weak_bg_fill = WIDGET_BACKGROUND;
	style.visuals.widgets.inactive.bg_stroke.color = WIDGET_STROKE;
	style.visuals.widgets.inactive.fg_stroke.color = WIDGET_FOREGROUND_NORMAL;

	style.visuals.widgets.hovered.bg_fill = WIDGET_HOVERED_BACKGROUND;
	style.visuals.widgets.hovered.weak_bg_fill = WIDGET_HOVERED_BACKGROUND;
	style.visuals.widgets.hovered.bg_stroke.color = WIDGET_HOVERED_STROKE;
	style.visuals.widgets.hovered.fg_stroke.color = WIDGET_FOREGROUND_LIGHT;

	style.visuals.widgets.active.bg_fill = WIDGET_ACTIVE_BACKGROUND;
	style.visuals.widgets.active.weak_bg_fill = WIDGET_ACTIVE_BACKGROUND;
	style.visuals.widgets.active.bg_stroke.color = WIDGET_ACTIVE_STROKE;
	style.visuals.widgets.active.fg_stroke.color = WIDGET_FOREGROUND_LIGHT;

	style.visuals.widgets.open.bg_fill = BACKGROUND;
	style.visuals.widgets.open.weak_bg_fill = BACKGROUND;
	style.visuals.widgets.open.bg_stroke.color = WIDGET_BACKGROUND;
	style.visuals.widgets.open.fg_stroke.color = WIDGET_FOREGROUND_NORMAL;

	style.visuals.window_stroke.color = WIDGET_BACKGROUND;
	style.visuals.window_fill = BACKGROUND;
	style.visuals.panel_fill = BACKGROUND;
	style.visuals.selection.bg_fill = SELECTION;
	style.visuals.selection.stroke.color = SELECTION_BRIGHT;
	style.visuals.text_cursor.stroke.color = SELECTION_BRIGHT;

	style.visuals.hyperlink_color = LINK_COLOUR;
}
