use super::utility_types::TransformIn;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::network_interface::NodeTemplate;
use crate::messages::prelude::*;
use glam::{DAffine2, DVec2};
use graph_craft::document::NodeId;
use graphene_std::Color;
use graphene_std::brush::brush_stroke::BrushStroke;
use graphene_std::raster::BlendMode;
use graphene_std::raster_types::Image;
use graphene_std::subpath::Subpath;
use graphene_std::text::{Font, TypesettingConfig};
use graphene_std::vector::style::{GradientForm, GradientHueDirection, GradientInterpolation, GradientSettings, GradientSpace, GradientSpread, Stroke};
use graphene_std::vector::{Gradient, PointId, VectorModificationType};

#[impl_message(Message, DocumentMessage, GraphOperation)]
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)]
pub enum GraphOperationMessage {
	FillColorSet {
		layer: LayerNodeIdentifier,
		color: Option<Color>,
	},
	ColorValueSet {
		layer: LayerNodeIdentifier,
		color: Color,
	},
	FillGradientSet {
		layer: LayerNodeIdentifier,
		#[serde(skip)]
		gradient: Gradient,
		gradient_form: GradientForm,
		gradient_settings: GradientSettings,
		transform: DAffine2,
	},
	BlendingFillSet {
		layer: LayerNodeIdentifier,
		fill: f64,
	},
	GradientStopsSet {
		layer: LayerNodeIdentifier,
		#[serde(skip)]
		stops: Gradient,
	},
	GradientPositionsSet {
		layer: LayerNodeIdentifier,
		positions: Vec<f64>,
	},
	GradientMidpointsSet {
		layer: LayerNodeIdentifier,
		midpoints: Vec<f64>,
	},
	GradientTransformSet {
		layer: LayerNodeIdentifier,
		transform: DAffine2,
	},
	GradientFormSet {
		layer: LayerNodeIdentifier,
		gradient_form: GradientForm,
	},
	GradientSpreadSet {
		layer: LayerNodeIdentifier,
		gradient_spread: GradientSpread,
	},
	GradientSpaceSet {
		layer: LayerNodeIdentifier,
		gradient_space: GradientSpace,
	},
	GradientCyclicSet {
		layer: LayerNodeIdentifier,
		gradient_cyclic: bool,
	},
	GradientHueDirectionSet {
		layer: LayerNodeIdentifier,
		gradient_hue_direction: GradientHueDirection,
	},
	GradientInterpolationSet {
		layer: LayerNodeIdentifier,
		gradient_interpolation: GradientInterpolation,
	},
	OpacitySet {
		layer: LayerNodeIdentifier,
		opacity: f64,
	},
	BlendModeSet {
		layer: LayerNodeIdentifier,
		blend_mode: BlendMode,
	},
	ClipModeToggle {
		layer: LayerNodeIdentifier,
	},
	StrokeSet {
		layer: LayerNodeIdentifier,
		color: Option<Color>,
		stroke: Stroke,
	},
	TransformChange {
		layer: LayerNodeIdentifier,
		transform: DAffine2,
		transform_in: TransformIn,
		skip_rerender: bool,
	},
	TransformSet {
		layer: LayerNodeIdentifier,
		transform: DAffine2,
		transform_in: TransformIn,
		skip_rerender: bool,
	},
	Vector {
		layer: LayerNodeIdentifier,
		modification_type: VectorModificationType,
	},
	Brush {
		layer: LayerNodeIdentifier,
		strokes: Vec<BrushStroke>,
	},
	SetUpstreamToChain {
		layer: LayerNodeIdentifier,
	},
	NewArtboard {
		id: NodeId,
		location: DVec2,
		dimensions: DVec2,
		background: Color,
		clip: bool,
	},
	NewBitmapLayer {
		id: NodeId,
		image: Image<Color>,
		parent: LayerNodeIdentifier,
		insert_index: usize,
	},
	NewInterpolationLayer {
		id: NodeId,
		control_path_id: NodeId,
		parent: LayerNodeIdentifier,
		insert_index: usize,
		blend_count: Option<usize>,
	},
	ConnectInterpolationControlPathToChildren {
		interpolation_layer_id: NodeId,
		control_path_id: NodeId,
	},
	NewBooleanOperationLayer {
		id: NodeId,
		operation: graphene_std::vector::misc::BooleanOperation,
		parent: LayerNodeIdentifier,
		insert_index: usize,
	},
	NewCustomLayer {
		id: NodeId,
		nodes: Vec<(NodeId, NodeTemplate)>,
		parent: LayerNodeIdentifier,
		insert_index: usize,
	},
	NewColorFillLayer {
		node_id: NodeId,
		color: Color,
		parent: LayerNodeIdentifier,
		insert_index: usize,
	},
	NewVectorLayer {
		id: NodeId,
		subpaths: Vec<Subpath<PointId>>,
		parent: LayerNodeIdentifier,
		insert_index: usize,
	},
	NewTextLayer {
		id: NodeId,
		text: String,
		font: Font,
		typesetting: TypesettingConfig,
		parent: LayerNodeIdentifier,
		insert_index: usize,
	},
	ResizeArtboard {
		layer: LayerNodeIdentifier,
		location: DVec2,
		dimensions: DVec2,
	},
	RemoveArtboards,
	NewSvg {
		id: NodeId,
		svg: String,
		transform: DAffine2,
		parent: LayerNodeIdentifier,
		insert_index: usize,
		/// When true, centers the SVG at the transform origin (clipboard paste / drag-drop). When false, keeps natural SVG coordinates (file-open flow).
		center: bool,
	},
}
