//! atproto-static-web   A simple web viewer for AT Proto.
//! Copyright (C) 2026  AverageHelper
//!
//! This program is free software: you can redistribute it and/or modify
//! it under the terms of the GNU General Public License as published by
//! the Free Software Foundation, either version 3 of the License, or
//! (at your option) any later version.
//!
//! This program is distributed in the hope that it will be useful,
//! but WITHOUT ANY WARRANTY; without even the implied warranty of
//! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//! GNU General Public License for more details.
//!
//! You should have received a copy of the GNU General Public License
//! along with this program.  If not, see <https://www.gnu.org/licenses/>.

use core::fmt::Display;
use serde::de;

#[derive(Debug)]
pub struct TooLongError {
	actual: usize,
	expected: ExpectedLength,
}

impl TooLongError {
	#[inline]
	pub const fn new(actual: usize, max: usize, kind: LengthKind) -> Self {
		Self {
			actual,
			expected: ExpectedLength { max, kind },
		}
	}

	#[inline]
	pub const fn actual(&self) -> usize {
		self.actual
	}

	#[inline]
	pub const fn expected(&self) -> &ExpectedLength {
		&self.expected
	}
}

/// Describes a value's expected maximum length.
#[derive(Debug)]
pub struct ExpectedLength {
	max: usize,
	kind: LengthKind,
}

#[derive(Debug)]
pub enum LengthKind {
	/// Number of bytes, e.g. [`String::len`]
	Bytes,

	/// Number of Unicode Grapheme Clusters, e.g. [`unicode_segmentation::UnicodeSegmentation::graphemes`]
	Graphemes,

	/// Number of elements, e.g. [`Vec::len`]
	Items,
}

impl Display for LengthKind {
	#[inline]
	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
		match self {
			Self::Bytes => write!(f, "bytes"),
			Self::Graphemes => write!(f, "grapheme clusters"),
			Self::Items => write!(f, "items"),
		}
	}
}

impl de::Expected for ExpectedLength {
	#[inline]
	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
		write!(f, "length at most {} {}", self.max, self.kind)
	}
}
