// SPDX-License-Identifier: LGPL-2.1-only
// Copyright (C) 2026 Liberux Labs, S. L. <info@liberux.net>

use crate::types::{ Color, Length, Rect };
use crate::render::Canvas;
use super::Element;

mod theme;

/// A horizontal divider line.
///
/// Renders a thin line across the full width of its layout rect,
/// with vertical padding above and below. Use to break a column into
/// visual sections — between settings groups, list categories or content
/// blocks. The line takes the divider colour from the active theme by
/// default; override with [`Self::color`] for custom palettes.
///
/// ```rust,no_run
/// # use ltk::{ column, separator, text, Element };
/// # #[ derive( Clone ) ] enum Msg {}
/// # fn _ex() -> Element<Msg> {
/// // In view():
/// column()
///     .push( text( "General" ) )
///     .push( separator() )
///     .push( text( "Network" ) )
/// .into()
/// # }
/// ```
pub struct Separator
{
	/// Stroke colour. Defaults to the theme's `divider` palette slot.
	pub( crate ) color:     Color,
	/// Line thickness. `None` follows the process [`crate::WidgetScaling`]
	/// mode; `Some( len )` pins it (including `Length::px( 0.0 )`).
	pub( crate ) thickness: Option<Length>,
	/// Vertical padding above and below the line, baked into
	/// `preferred_size` so the divider visually centres in the row a
	/// parent column allocates. `None` follows the
	/// [`crate::WidgetScaling`] mode; `Some( len )` pins it — pass
	/// `Length::px( 0.0 )` for a flush, padding-less divider.
	pub( crate ) pad_v:     Option<Length>,
}

impl Separator
{
	/// Create a separator with the theme's default divider colour; the
	/// thickness follows the widget-scaling default unless overridden.
	pub fn new() -> Self
	{
		Self
		{
			color:     theme::color(),
			thickness: None,
			pad_v:     None,
		}
	}

	/// Resolve the line thickness: an explicit value wins, otherwise the
	/// widget-scaling default.
	fn resolved_thickness( &self, canvas: &Canvas ) -> f32
	{
		self.thickness
			.map( |l| canvas.resolve_geom( l ) )
			.unwrap_or_else( || canvas.geom_px( theme::THICKNESS ) )
	}

	/// Resolve the vertical padding: an explicit value wins, otherwise the
	/// widget-scaling default.
	fn resolved_pad_v( &self, canvas: &Canvas ) -> f32
	{
		self.pad_v
			.map( |l| canvas.resolve_geom( l ) )
			.unwrap_or_else( || canvas.geom_px( theme::PAD_V ) )
	}

	/// Override the stroke colour. Useful for emphasised dividers between
	/// destructive actions.
	pub fn color( mut self, color: Color ) -> Self
	{
		self.color = color;
		self
	}

	/// Override the line thickness. Accepts logical `f32` pixels or any
	/// [`Length`]. Without this it follows the widget-scaling mode.
	pub fn thickness( mut self, t: impl Into<Length> ) -> Self
	{
		self.thickness = Some( t.into() );
		self
	}

	/// Override the vertical padding above and below the line. Accepts
	/// logical `f32` pixels or any [`Length`]; pass `0.0` for a flush,
	/// padding-less divider. Without this it follows the widget-scaling mode.
	pub fn pad_v( mut self, p: impl Into<Length> ) -> Self
	{
		self.pad_v = Some( p.into() );
		self
	}

	/// Return the preferred `(width, height)`. Width is `max_width`;
	/// height is `thickness + 2 × pad_v`.
	pub fn preferred_size( &self, max_width: f32, canvas: &Canvas ) -> (f32, f32)
	{
		( max_width, self.resolved_thickness( canvas ) + self.resolved_pad_v( canvas ) * 2.0 )
	}

	/// Draw the divider line into `canvas` at `rect`.
	pub fn draw( &self, canvas: &mut Canvas, rect: Rect )
	{
		let y = rect.y + rect.height / 2.0;
		let thickness = self.resolved_thickness( canvas );
		canvas.draw_line( rect.x, y, rect.x + rect.width, y, self.color, thickness );
	}
}

/// Create a default [`Separator`] (theme divider colour, widget-scaling
/// default thickness unless overridden).
///
/// ```rust,no_run
/// # use ltk::{ column, separator, text, Element };
/// # #[ derive( Clone ) ] enum Msg {}
/// # fn _ex() -> Element<Msg> {
/// column()
///     .push( text( "Section A" ) )
///     .push( separator() )
///     .push( text( "Section B" ) )
/// .into()
/// # }
/// ```
pub fn separator() -> Separator
{
	Separator::new()
}

impl<Msg: Clone> From<Separator> for Element<Msg>
{
	fn from( s: Separator ) -> Self
	{
		Element::Separator( s )
	}
}

#[ cfg( test ) ]
mod tests;
