//! atproto-static-web   A simple web viewer for AT Proto.
//! Copyright (C) 2025  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 crate::atproto::{DecentralizedIdentifier, Handle};
use std::str::FromStr;

/// See https://atproto.com/specs/at-uri-scheme#structure
// Spec: "The authority part of the URI can be either a handle or a DID, indicating the identity associated with the repository."
#[derive(Debug, PartialEq, Eq)]
pub enum Authority {
	Did(DecentralizedIdentifier),
	Handle(Handle),
}

impl core::fmt::Display for Authority {
	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
		match self {
			Self::Did(did) => write!(f, "{did}"),
			Self::Handle(handle) => write!(f, "{handle}"),
		}
	}
}

impl From<DecentralizedIdentifier> for Authority {
	fn from(value: DecentralizedIdentifier) -> Self {
		Self::Did(value)
	}
}

impl From<Handle> for Authority {
	fn from(value: Handle) -> Self {
		Self::Handle(value)
	}
}

impl FromStr for Authority {
	type Err = AuthorityParseError;

	fn from_str(s: &str) -> Result<Self, Self::Err> {
		match s.parse::<DecentralizedIdentifier>() {
			Ok(did) => Ok(did.into()),
			Err(did_err) => match s.parse::<Handle>() {
				Ok(handle) => Ok(handle.into()),
				Err(handle_err) => Err(AuthorityParseError(did_err, handle_err)),
			},
		}
	}
}

#[derive(Debug)]
pub struct AuthorityParseError(
	<DecentralizedIdentifier as FromStr>::Err,
	<Handle as FromStr>::Err,
);

impl core::fmt::Display for AuthorityParseError {
	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
		write!(
			f,
			"could not parse string as either DID ({}) or Handle ({})",
			self.0, self.1
		)
	}
}

impl core::error::Error for AuthorityParseError {}
