//! work in progress

use derive_setters::Setters;
use glam::{vec2, Vec2};

use crate::{
  draw::{RoundedCorners, UiDrawCommand},
  element::{MeasureContext, ProcessContext, UiElement},
  layout::{compute_size, Size2d},
  measure::Response,
  rectangle::Corners,
  signal::{SignalStore, UiSignal},
};

/// work in progress
#[derive(Default, Setters)]
#[setters(prefix = "with_")]
pub struct Slider {
  pub value: f32,
  pub size: Size2d,

  #[setters(skip)]
  fire_on_shit: Option<Box<dyn Fn(&mut SignalStore, f32)>>,
}

impl Slider {
  pub const DEFAULT_HEIGHT: f32 = 20.0;

  pub fn new(value: f32) -> Self {
    Self {
      value,
      ..Default::default()
    }
  }

  pub fn on_change<S: UiSignal + 'static, T: Fn(f32) -> S + 'static>(self, f: T) -> Self {
    Self {
      fire_on_shit: Some(Box::new(move |s: &mut SignalStore, x| {
        s.add::<S>(f(x));
      })),
      ..self
    }
  }
}

impl UiElement for Slider {
  fn name(&self) -> &'static str {
    "Slider"
  }

  fn measure(&self, ctx: MeasureContext) -> Response {
    Response {
      size: compute_size(ctx.layout, self.size, (ctx.layout.max_size.x, Self::DEFAULT_HEIGHT).into()),
      ..Default::default()
    }
  }

  fn process(&self, ctx: ProcessContext) {
    let bgrect_height_ratio = 0.25;
    ctx.draw.add(UiDrawCommand::Rectangle {
      position: ctx.layout.position + ctx.measure.size * vec2(0., 0.5 - bgrect_height_ratio / 2.),
      size: ctx.measure.size * vec2(1., bgrect_height_ratio),
      color: Corners::all((1., 1., 1., 0.7).into()),
      texture: None,
      rounded_corners: None,
      //Some(RoundedCorners::from_radius(Corners::all(bgrect_height_ratio * ctx.measure.size.y * 0.4))),
    });

    let value = self.value.clamp(0., 1.);
    let handle_size = vec2(15., ctx.measure.size.y);
    ctx.draw.add(UiDrawCommand::Rectangle {
      position: ctx.layout.position + (ctx.measure.size.x * value - handle_size.x / 2.) * Vec2::X,
      size: handle_size,
      color: Corners::all((1., 1., 1., 1.).into()),
      texture: None,
      rounded_corners: None,
      //Some(RoundedCorners::from_radius(Corners::all(handle_size.x / 3.))),
    });

    //handle click etc
    if let Some(res) = ctx.input.check_active(ctx.measure.rect(ctx.layout.position)) {
      let new_value = (res.position_in_rect.x / ctx.measure.size.x).clamp(0., 1.);
      if let Some(fire) = &self.fire_on_shit {
        fire(ctx.signal, new_value);
      }
      //TODO call signal with new value
    }
  }
}

//TODO