use std::{
	cmp::Ordering, collections::HashMap, hash::{Hash, Hasher}
};
use super::{
	AmadeusOrd, Bson, Date, DateTime, DateTimeWithoutTimezone, DateWithoutTimezone, Decimal, Enum, Group, IpAddr, Json, List, Time, TimeWithoutTimezone, Timezone, Url, Value, Webpage
};
#[derive(Clone, PartialEq, Debug)]
pub enum ValueRequired {
	
	
	Bool(bool),
	
	U8(u8),
	
	I8(i8),
	
	U16(u16),
	
	I16(i16),
	
	U32(u32),
	
	I32(i32),
	
	U64(u64),
	
	I64(i64),
	
	F32(f32),
	
	F64(f64),
	
	
	Date(Date),
	
	
	DateWithoutTimezone(DateWithoutTimezone),
	
	Time(Time),
	
	TimeWithoutTimezone(TimeWithoutTimezone),
	
	DateTime(DateTime),
	
	DateTimeWithoutTimezone(DateTimeWithoutTimezone),
	
	Timezone(Timezone),
	
	Decimal(Decimal),
	
	Bson(Bson),
	
	String(String),
	
	Json(Json),
	
	Enum(Enum),
	
	Url(Url),
	
	Webpage(Webpage<'static>),
	
	IpAddr(IpAddr),
	
	
	List(List<Value>),
	
	Map(HashMap<Value, Value>),
	
	Group(Group),
}
#[allow(clippy::derive_hash_xor_eq)]
impl Hash for ValueRequired {
	fn hash<H: Hasher>(&self, state: &mut H) {
		match self {
			Self::Bool(value) => {
				0_u8.hash(state);
				value.hash(state);
			}
			Self::U8(value) => {
				1_u8.hash(state);
				value.hash(state);
			}
			Self::I8(value) => {
				2_u8.hash(state);
				value.hash(state);
			}
			Self::U16(value) => {
				3_u8.hash(state);
				value.hash(state);
			}
			Self::I16(value) => {
				4_u8.hash(state);
				value.hash(state);
			}
			Self::U32(value) => {
				5_u8.hash(state);
				value.hash(state);
			}
			Self::I32(value) => {
				6_u8.hash(state);
				value.hash(state);
			}
			Self::U64(value) => {
				7_u8.hash(state);
				value.hash(state);
			}
			Self::I64(value) => {
				8_u8.hash(state);
				value.hash(state);
			}
			Self::F32(_value) => {
				9_u8.hash(state);
			}
			Self::F64(_value) => {
				10_u8.hash(state);
			}
			Self::Date(value) => {
				11_u8.hash(state);
				value.hash(state);
			}
			Self::DateWithoutTimezone(value) => {
				11_u8.hash(state);
				value.hash(state);
			}
			Self::Time(value) => {
				12_u8.hash(state);
				value.hash(state);
			}
			Self::TimeWithoutTimezone(value) => {
				12_u8.hash(state);
				value.hash(state);
			}
			Self::DateTime(value) => {
				13_u8.hash(state);
				value.hash(state);
			}
			Self::DateTimeWithoutTimezone(value) => {
				13_u8.hash(state);
				value.hash(state);
			}
			Self::Timezone(value) => {
				13_u8.hash(state);
				value.hash(state);
			}
			Self::Decimal(_value) => {
				14_u8.hash(state);
			}
			Self::Bson(value) => {
				15_u8.hash(state);
				value.hash(state);
			}
			Self::String(value) => {
				16_u8.hash(state);
				value.hash(state);
			}
			Self::Json(value) => {
				17_u8.hash(state);
				value.hash(state);
			}
			Self::Enum(value) => {
				18_u8.hash(state);
				value.hash(state);
			}
			Self::Url(value) => {
				19_u8.hash(state);
				value.hash(state);
			}
			Self::Webpage(value) => {
				20_u8.hash(state);
				value.hash(state);
			}
			Self::IpAddr(value) => {
				21_u8.hash(state);
				value.hash(state);
			}
			Self::List(value) => {
				22_u8.hash(state);
				value.hash(state);
			}
			Self::Map(_value) => {
				23_u8.hash(state);
			}
			Self::Group(_value) => {
				24_u8.hash(state);
			}
		}
	}
}
impl Eq for ValueRequired {}
impl PartialOrd for ValueRequired {
	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
		match (self, other) {
			(Self::Bool(a), Self::Bool(b)) => a.partial_cmp(b),
			(Self::U8(a), Self::U8(b)) => a.partial_cmp(b),
			(Self::I8(a), Self::I8(b)) => a.partial_cmp(b),
			(Self::U16(a), Self::U16(b)) => a.partial_cmp(b),
			(Self::I16(a), Self::I16(b)) => a.partial_cmp(b),
			(Self::U32(a), Self::U32(b)) => a.partial_cmp(b),
			(Self::I32(a), Self::I32(b)) => a.partial_cmp(b),
			(Self::U64(a), Self::U64(b)) => a.partial_cmp(b),
			(Self::I64(a), Self::I64(b)) => a.partial_cmp(b),
			(Self::F32(a), Self::F32(b)) => a.partial_cmp(b),
			(Self::F64(a), Self::F64(b)) => a.partial_cmp(b),
			(Self::Date(a), Self::Date(b)) => a.partial_cmp(b),
			(Self::DateWithoutTimezone(a), Self::DateWithoutTimezone(b)) => a.partial_cmp(b),
			(Self::Time(a), Self::Time(b)) => a.partial_cmp(b),
			(Self::TimeWithoutTimezone(a), Self::TimeWithoutTimezone(b)) => a.partial_cmp(b),
			(Self::DateTime(a), Self::DateTime(b)) => a.partial_cmp(b),
			(Self::DateTimeWithoutTimezone(a), Self::DateTimeWithoutTimezone(b)) => {
				a.partial_cmp(b)
			}
			(Self::Timezone(a), Self::Timezone(b)) => a.partial_cmp(b),
			(Self::Decimal(a), Self::Decimal(b)) => a.partial_cmp(b),
			(Self::Bson(a), Self::Bson(b)) => a.partial_cmp(b),
			(Self::String(a), Self::String(b)) => a.partial_cmp(b),
			(Self::Json(a), Self::Json(b)) => a.partial_cmp(b),
			(Self::Enum(a), Self::Enum(b)) => a.partial_cmp(b),
			(Self::Url(a), Self::Url(b)) => a.partial_cmp(b),
			(Self::Webpage(a), Self::Webpage(b)) => a.partial_cmp(b),
			(Self::IpAddr(a), Self::IpAddr(b)) => a.partial_cmp(b),
			(Self::List(a), Self::List(b)) => a.partial_cmp(b),
			(Self::Map(_a), Self::Map(_b)) => None, 
			(Self::Group(a), Self::Group(b)) => a.partial_cmp(b),
			_ => None,
		}
	}
}
impl AmadeusOrd for ValueRequired {
	fn amadeus_cmp(&self, other: &Self) -> Ordering {
		match (self, other) {
			(Self::Bool(a), Self::Bool(b)) => a.amadeus_cmp(b),
			(Self::U8(a), Self::U8(b)) => a.amadeus_cmp(b),
			(Self::I8(a), Self::I8(b)) => a.amadeus_cmp(b),
			(Self::U16(a), Self::U16(b)) => a.amadeus_cmp(b),
			(Self::I16(a), Self::I16(b)) => a.amadeus_cmp(b),
			(Self::U32(a), Self::U32(b)) => a.amadeus_cmp(b),
			(Self::I32(a), Self::I32(b)) => a.amadeus_cmp(b),
			(Self::U64(a), Self::U64(b)) => a.amadeus_cmp(b),
			(Self::I64(a), Self::I64(b)) => a.amadeus_cmp(b),
			(Self::F32(a), Self::F32(b)) => a.amadeus_cmp(b),
			(Self::F64(a), Self::F64(b)) => a.amadeus_cmp(b),
			(Self::Date(a), Self::Date(b)) => a.amadeus_cmp(b),
			(Self::DateWithoutTimezone(a), Self::DateWithoutTimezone(b)) => a.amadeus_cmp(b),
			(Self::Time(a), Self::Time(b)) => a.amadeus_cmp(b),
			(Self::TimeWithoutTimezone(a), Self::TimeWithoutTimezone(b)) => a.amadeus_cmp(b),
			(Self::DateTime(a), Self::DateTime(b)) => a.amadeus_cmp(b),
			(Self::DateTimeWithoutTimezone(a), Self::DateTimeWithoutTimezone(b)) => {
				a.amadeus_cmp(b)
			}
			(Self::Timezone(a), Self::Timezone(b)) => a.amadeus_cmp(b),
			(Self::Decimal(a), Self::Decimal(b)) => a.amadeus_cmp(b),
			(Self::Bson(a), Self::Bson(b)) => a.amadeus_cmp(b),
			(Self::String(a), Self::String(b)) => a.amadeus_cmp(b),
			(Self::Json(a), Self::Json(b)) => a.amadeus_cmp(b),
			(Self::Enum(a), Self::Enum(b)) => a.amadeus_cmp(b),
			(Self::Url(a), Self::Url(b)) => a.amadeus_cmp(b),
			(Self::Webpage(a), Self::Webpage(b)) => a.amadeus_cmp(b),
			(Self::IpAddr(a), Self::IpAddr(b)) => a.amadeus_cmp(b),
			(Self::List(a), Self::List(b)) => a.amadeus_cmp(b),
			(Self::Map(a), Self::Map(b)) => a.amadeus_cmp(b),
			(Self::Group(a), Self::Group(b)) => a.amadeus_cmp(b),
			_ => unimplemented!(),
		}
	}
}
impl From<ValueRequired> for Value {
	fn from(value: ValueRequired) -> Self {
		match value {
			ValueRequired::Bool(value) => Self::Bool(value),
			ValueRequired::U8(value) => Self::U8(value),
			ValueRequired::I8(value) => Self::I8(value),
			ValueRequired::U16(value) => Self::U16(value),
			ValueRequired::I16(value) => Self::I16(value),
			ValueRequired::U32(value) => Self::U32(value),
			ValueRequired::I32(value) => Self::I32(value),
			ValueRequired::U64(value) => Self::U64(value),
			ValueRequired::I64(value) => Self::I64(value),
			ValueRequired::F32(value) => Self::F32(value),
			ValueRequired::F64(value) => Self::F64(value),
			ValueRequired::Date(value) => Self::Date(value),
			ValueRequired::DateWithoutTimezone(value) => Self::DateWithoutTimezone(value),
			ValueRequired::Time(value) => Self::Time(value),
			ValueRequired::TimeWithoutTimezone(value) => Self::TimeWithoutTimezone(value),
			ValueRequired::DateTime(value) => Self::DateTime(value),
			ValueRequired::DateTimeWithoutTimezone(value) => Self::DateTimeWithoutTimezone(value),
			ValueRequired::Timezone(value) => Self::Timezone(value),
			ValueRequired::Decimal(value) => Self::Decimal(value),
			ValueRequired::Bson(value) => Self::Bson(value),
			ValueRequired::String(value) => Self::String(value),
			ValueRequired::Json(value) => Self::Json(value),
			ValueRequired::Enum(value) => Self::Enum(value),
			ValueRequired::Url(value) => Self::Url(value),
			ValueRequired::Webpage(value) => Self::Webpage(value),
			ValueRequired::IpAddr(value) => Self::IpAddr(value),
			ValueRequired::List(value) => Self::List(value),
			ValueRequired::Map(value) => Self::Map(value),
			ValueRequired::Group(value) => Self::Group(value),
		}
	}
}
impl From<Value> for Option<ValueRequired> {
	fn from(value: Value) -> Self {
		Some(match value {
			Value::Bool(value) => ValueRequired::Bool(value),
			Value::U8(value) => ValueRequired::U8(value),
			Value::I8(value) => ValueRequired::I8(value),
			Value::U16(value) => ValueRequired::U16(value),
			Value::I16(value) => ValueRequired::I16(value),
			Value::U32(value) => ValueRequired::U32(value),
			Value::I32(value) => ValueRequired::I32(value),
			Value::U64(value) => ValueRequired::U64(value),
			Value::I64(value) => ValueRequired::I64(value),
			Value::F32(value) => ValueRequired::F32(value),
			Value::F64(value) => ValueRequired::F64(value),
			Value::Date(value) => ValueRequired::Date(value),
			Value::DateWithoutTimezone(value) => ValueRequired::DateWithoutTimezone(value),
			Value::Time(value) => ValueRequired::Time(value),
			Value::TimeWithoutTimezone(value) => ValueRequired::TimeWithoutTimezone(value),
			Value::DateTime(value) => ValueRequired::DateTime(value),
			Value::DateTimeWithoutTimezone(value) => ValueRequired::DateTimeWithoutTimezone(value),
			Value::Timezone(value) => ValueRequired::Timezone(value),
			Value::Decimal(value) => ValueRequired::Decimal(value),
			Value::Bson(value) => ValueRequired::Bson(value),
			Value::String(value) => ValueRequired::String(value),
			Value::Json(value) => ValueRequired::Json(value),
			Value::Enum(value) => ValueRequired::Enum(value),
			Value::Url(value) => ValueRequired::Url(value),
			Value::Webpage(value) => ValueRequired::Webpage(value),
			Value::IpAddr(value) => ValueRequired::IpAddr(value),
			Value::List(value) => ValueRequired::List(value),
			Value::Map(value) => ValueRequired::Map(value),
			Value::Group(value) => ValueRequired::Group(value),
			Value::Option(_) => return None,
		})
	}
}