#[cfg(feature = "diesel")]
use std::str::FromStr;
#[cfg(feature = "diesel")]
use diesel::{mysql::Mysql, serialize::ToSql, sql_types::Text};
#[cfg(feature = "diesel")]
use diesel_derives::{AsExpression, FromSqlRow};
use enum_iterator::Sequence;
use kittycad_execution_plan_macros::ExecutionPlanValue;
use kittycad_execution_plan_traits as kcep;
use parse_display_derive::{Display, FromStr};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[cfg(feature = "cxx")]
use crate::impl_extern_type;
use crate::{length_unit::LengthUnit, units::UnitAngle};
macro_rules! impl_string_enum_sql {
    {$name:ident} => {
        #[cfg(feature = "diesel")]
        impl diesel::serialize::ToSql<Text, Mysql> for $name {
            fn to_sql<'a>(&'a self, out: &mut diesel::serialize::Output<'a, '_, Mysql>) -> diesel::serialize::Result {
                <String as ToSql<Text, Mysql>>::to_sql(&self.to_string(), &mut out.reborrow())
            }
        }
        #[cfg(feature = "diesel")]
        impl<DB> diesel::deserialize::FromSql<Text, DB> for $name
        where
            DB: diesel::backend::Backend,
            String: diesel::deserialize::FromSql<Text, DB>,
        {
            fn from_sql(bytes: <DB as diesel::backend::Backend>::RawValue<'_>) -> diesel::deserialize::Result<Self> {
                Ok(Self::from_str(&String::from_sql(bytes)?)?)
            }
        }
    };
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct AnnotationOptions {
    pub text: Option<AnnotationTextOptions>,
    pub line_ends: Option<AnnotationLineEndOptions>,
    pub line_width: Option<f32>,
    pub color: Option<Color>,
    pub position: Option<Point3d<f32>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct AnnotationLineEndOptions {
    pub start: AnnotationLineEnd,
    pub end: AnnotationLineEnd,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct AnnotationTextOptions {
    pub x: AnnotationTextAlignmentX,
    pub y: AnnotationTextAlignmentY,
    pub text: String,
    pub point_size: u32,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case", tag = "type")]
pub enum DistanceType {
    Euclidean {},
    OnAxis {
        axis: GlobalAxis,
    },
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, ExecutionPlanValue)]
pub struct Color {
    pub r: f32,
    pub g: f32,
    pub b: f32,
    pub a: f32,
}
#[allow(missing_docs)]
#[derive(
    Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Sequence, Clone, Ord, PartialOrd,
)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
#[serde(rename_all = "lowercase")]
pub enum AnnotationTextAlignmentX {
    Left,
    Center,
    Right,
}
impl_string_enum_sql! {AnnotationTextAlignmentX}
#[allow(missing_docs)]
#[derive(
    Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Sequence, Clone, Ord, PartialOrd,
)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
#[serde(rename_all = "lowercase")]
pub enum AnnotationTextAlignmentY {
    Bottom,
    Center,
    Top,
}
impl_string_enum_sql! {AnnotationTextAlignmentY}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Default, ExecutionPlanValue)]
#[serde(rename = "Point3d")]
#[serde(rename_all = "snake_case")]
pub struct Point3d<T = f32>
where
    kcep::Primitive: From<T>,
    T: kcep::Value,
{
    #[allow(missing_docs)]
    pub x: T,
    #[allow(missing_docs)]
    pub y: T,
    #[allow(missing_docs)]
    pub z: T,
}
#[allow(missing_docs)]
#[derive(
    Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Sequence, Clone, Ord, PartialOrd,
)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
#[serde(rename_all = "lowercase")]
pub enum AnnotationLineEnd {
    None,
    Arrow,
}
impl_string_enum_sql! {AnnotationLineEnd}
#[derive(
    Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Sequence, Clone, Ord, PartialOrd,
)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
#[serde(rename_all = "lowercase")]
pub enum AnnotationType {
    T2D,
    T3D,
}
impl_string_enum_sql! {AnnotationType}
#[derive(
    Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Sequence, Clone, Ord, PartialOrd,
)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
#[serde(rename_all = "lowercase")]
pub enum CameraDragInteractionType {
    Pan,
    Rotate,
    Zoom,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, ExecutionPlanValue)]
#[serde(rename_all = "snake_case", tag = "type")]
pub enum PathSegment {
    Line {
        end: Point3d<LengthUnit>,
        relative: bool,
    },
    Arc {
        center: Point2d<LengthUnit>,
        radius: LengthUnit,
        start: Angle,
        end: Angle,
        relative: bool,
    },
    Bezier {
        control1: Point3d<LengthUnit>,
        control2: Point3d<LengthUnit>,
        end: Point3d<LengthUnit>,
        relative: bool,
    },
    TangentialArc {
        radius: LengthUnit,
        offset: Angle,
    },
    TangentialArcTo {
        to: Point3d<LengthUnit>,
        angle_snap_increment: Option<Angle>,
    },
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, ExecutionPlanValue)]
#[serde(rename = "Point4d")]
#[serde(rename_all = "snake_case")]
pub struct Point4d<T = f32>
where
    kcep::Primitive: From<T>,
    T: kcep::Value,
{
    #[allow(missing_docs)]
    pub x: T,
    #[allow(missing_docs)]
    pub y: T,
    #[allow(missing_docs)]
    pub z: T,
    #[allow(missing_docs)]
    pub w: T,
}
impl From<euler::Vec3> for Point3d<f32> {
    fn from(v: euler::Vec3) -> Self {
        Self { x: v.x, y: v.y, z: v.z }
    }
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, Default, ExecutionPlanValue)]
#[serde(rename = "Point2d")]
#[serde(rename_all = "snake_case")]
pub struct Point2d<T = f32>
where
    kcep::Primitive: From<T>,
    T: kcep::Value,
{
    #[allow(missing_docs)]
    pub x: T,
    #[allow(missing_docs)]
    pub y: T,
}
#[derive(Clone, Copy, PartialEq, Debug, JsonSchema, Deserialize, Serialize)]
pub struct Angle {
    pub unit: UnitAngle,
    pub value: f64,
}
impl Angle {
    pub fn to_degrees(self) -> f64 {
        match self.unit {
            UnitAngle::Degrees => self.value,
            UnitAngle::Radians => self.value.to_degrees(),
        }
    }
    pub fn from_degrees(value: f64) -> Self {
        Self {
            unit: UnitAngle::Degrees,
            value,
        }
    }
    pub fn from_radians(value: f64) -> Self {
        Self {
            unit: UnitAngle::Radians,
            value,
        }
    }
}
#[derive(
    Display,
    FromStr,
    Copy,
    Eq,
    PartialEq,
    Debug,
    JsonSchema,
    Deserialize,
    Serialize,
    Sequence,
    Clone,
    Ord,
    PartialOrd,
    ExecutionPlanValue,
)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
#[serde(rename_all = "lowercase")]
pub enum SceneSelectionType {
    Replace,
    Add,
    Remove,
}
impl_string_enum_sql! {SceneSelectionType}
#[allow(missing_docs)]
#[derive(
    Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Sequence, Clone, Ord, PartialOrd,
)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
#[serde(rename_all = "snake_case")]
pub enum SceneToolType {
    CameraRevolve,
    Select,
    Move,
    SketchLine,
    SketchTangentialArc,
    SketchCurve,
    SketchCurveMod,
}
impl_string_enum_sql! {SceneToolType}
#[allow(missing_docs)]
#[derive(
    Display,
    FromStr,
    Copy,
    Eq,
    PartialEq,
    Debug,
    JsonSchema,
    Deserialize,
    Serialize,
    Sequence,
    Clone,
    Ord,
    PartialOrd,
    Default,
)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
#[serde(rename_all = "snake_case")]
pub enum PathComponentConstraintBound {
    #[default]
    Unconstrained,
    PartiallyConstrained,
    FullyConstrained,
}
impl_string_enum_sql! {PathComponentConstraintBound}
#[allow(missing_docs)]
#[derive(
    Display,
    FromStr,
    Copy,
    Eq,
    PartialEq,
    Debug,
    JsonSchema,
    Deserialize,
    Serialize,
    Sequence,
    Clone,
    Ord,
    PartialOrd,
    Default,
)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
#[serde(rename_all = "snake_case")]
pub enum PathComponentConstraintType {
    #[default]
    Unconstrained,
    Vertical,
    Horizontal,
    EqualLength,
    Parallel,
    AngleBetween,
}
impl_string_enum_sql! {PathComponentConstraintType}
#[allow(missing_docs)]
#[derive(
    Display,
    FromStr,
    Copy,
    Eq,
    PartialEq,
    Debug,
    JsonSchema,
    Deserialize,
    Serialize,
    Sequence,
    Clone,
    Ord,
    PartialOrd,
    ExecutionPlanValue,
)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
#[serde(rename_all = "snake_case")]
pub enum PathCommand {
    MoveTo,
    LineTo,
    BezCurveTo,
    NurbsCurveTo,
    AddArc,
}
#[allow(missing_docs)]
#[derive(
    Display,
    FromStr,
    Copy,
    Eq,
    PartialEq,
    Debug,
    JsonSchema,
    Deserialize,
    Serialize,
    Sequence,
    Clone,
    Ord,
    PartialOrd,
    ExecutionPlanValue,
)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
#[serde(rename_all = "lowercase")]
#[repr(u8)]
pub enum EntityType {
    Entity,
    Object,
    Path,
    Curve,
    Solid2D,
    Solid3D,
    Edge,
    Face,
    Plane,
    Vertex,
}
#[allow(missing_docs)]
#[derive(
    Display,
    FromStr,
    Copy,
    Eq,
    PartialEq,
    Debug,
    JsonSchema,
    Deserialize,
    Serialize,
    Sequence,
    Clone,
    Ord,
    PartialOrd,
    ExecutionPlanValue,
)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
#[serde(rename_all = "snake_case")]
pub enum CurveType {
    Line,
    Arc,
    Nurbs,
}
#[derive(Debug, Serialize, Deserialize, JsonSchema, ExecutionPlanValue)]
pub struct ExportFile {
    pub name: String,
    pub contents: crate::base64::Base64Data,
}
#[derive(
    Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Clone, Ord, PartialOrd, Sequence,
)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
#[serde(rename_all = "lowercase")]
#[display(style = "lowercase")]
pub enum FileExportFormat {
    Fbx,
    Glb,
    Gltf,
    Obj,
    Ply,
    Step,
    Stl,
}
impl_string_enum_sql! {FileExportFormat}
#[derive(
    Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Clone, Ord, PartialOrd, Sequence,
)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
#[serde(rename_all = "lowercase")]
#[display(style = "lowercase")]
pub enum FileImportFormat {
    Fbx,
    Gltf,
    Obj,
    Ply,
    Sldprt,
    Step,
    Stl,
}
#[derive(Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Clone, Ord, PartialOrd)]
#[serde(rename_all = "snake_case")]
pub enum EngineErrorCode {
    BadRequest = 1,
    InternalEngine,
}
impl From<EngineErrorCode> for http::StatusCode {
    fn from(e: EngineErrorCode) -> Self {
        match e {
            EngineErrorCode::BadRequest => Self::BAD_REQUEST,
            EngineErrorCode::InternalEngine => Self::INTERNAL_SERVER_ERROR,
        }
    }
}
impl_string_enum_sql! {FileImportFormat}
#[derive(Copy, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Clone, PartialOrd, ExecutionPlanValue)]
#[serde(rename_all = "snake_case")]
pub struct PerspectiveCameraParameters {
    pub fov_y: f32,
    pub z_near: f32,
    pub z_far: f32,
}
#[derive(
    Display, FromStr, Copy, Eq, PartialEq, Debug, JsonSchema, Deserialize, Serialize, Sequence, Clone, Ord, PartialOrd,
)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
#[serde(rename_all = "lowercase")]
pub enum GlobalAxis {
    X,
    Y,
    Z,
}
impl_string_enum_sql! {GlobalAxis}
#[derive(
    Display,
    FromStr,
    Copy,
    Eq,
    PartialEq,
    Debug,
    JsonSchema,
    Deserialize,
    Serialize,
    Sequence,
    Clone,
    Ord,
    PartialOrd,
    ExecutionPlanValue,
)]
#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))]
#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
#[serde(rename_all = "snake_case")]
#[repr(u8)]
pub enum ExtrusionFaceCapType {
    None,
    Top,
    Bottom,
}
impl_string_enum_sql! {ExtrusionFaceCapType}
#[cfg(feature = "cxx")]
impl_extern_type! {
    [Trivial]
    FileImportFormat = "Enums::_FileImportFormat"
    FileExportFormat = "Enums::_FileExportFormat"
    CameraDragInteractionType = "Enums::_CameraDragInteractionType"
    SceneSelectionType = "Enums::_SceneSelectionType"
    SceneToolType = "Enums::_SceneToolType"
    EntityType = "Enums::_EntityType"
    AnnotationType = "Enums::_AnnotationType"
    AnnotationTextAlignmentX = "Enums::_AnnotationTextAlignmentX"
    AnnotationTextAlignmentY = "Enums::_AnnotationTextAlignmentY"
    AnnotationLineEnd = "Enums::_AnnotationLineEnd"
    CurveType = "Enums::_CurveType"
    PathCommand = "Enums::_PathCommand"
    PathComponentConstraintBound = "Enums::_PathComponentConstraintBound"
    PathComponentConstraintType = "Enums::_PathComponentConstraintType"
    ExtrusionFaceCapType  = "Enums::_ExtrusionFaceCapType"
    EngineErrorCode = "Enums::_ErrorCode"
    GlobalAxis = "Enums::_GlobalAxis"
}