extends "res://addons/property_panel/property_panel.gd"

## Panel exposing brush properties.

var _editable_brush : EditableBrush

const SYMMETRY_AXIS := {
	none = Vector3.ZERO,
	x = Vector3.RIGHT,
	y = Vector3.UP,
	z = Vector3.FORWARD,
}

class EditableBrush:
	var brush: Brush

	func _init(_brush):
		brush = _brush
	
	static func load_texture(path: String) -> Texture2D:
		if not FileAccess.file_exists(path):
			return null
		if ResourceLoader.exists(path):
			return load(path)
		return ImageTexture.create_from_image(Image.load_from_file(path))
	
	func _set(property: StringName, value: Variant) -> bool:
		match str(property):
			"color":
				# TODO: Maybe expose all channels.
				brush.colors = [value, value, value, Color(0.5, 0.5, 1.0)]
			"texture":
				var texture := EditableBrush.load_texture(value as String)
				if texture:
					brush.textures = [texture]
				else:
					brush.textures = []
			"stencil":
				brush.stencil = EditableBrush.load_texture(value as String)
			"symmetry":
				brush.symmetry = Brush.Symmetry[value]
			"symmetry_axis":
				brush.symmetry_axis = SYMMETRY_AXIS[value]
			"projection":
				brush.projection = Brush.BrushProjection[value]
			"size_space":
				brush.size_space = Brush.SizeSpace[value]
			"tip":
				brush.tip = EditableBrush.load_texture(value as String)
			_:
				if property in brush:
					brush[property] = value
				else:
					return false
		return true

	func _get(property: StringName):
		match str(property):
			"color":
				return brush.get_color(0)
			"texture":
				return brush.get_texture(0)
			"stencil":
				@warning_ignore("incompatible_ternary")
				return null if not brush.stencil else brush.stencil.resource_path
			"symmetry":
				return Brush.Symmetry.keys()[brush.symmetry]
			"symmetry_axis":
				return SYMMETRY_AXIS.values()[SYMMETRY_AXIS.values().find(brush.symmetry_axis)]
			"projection":
				return Brush.BrushProjection.keys()[brush.projection]
			"size_space":
				return Brush.SizeSpace.keys()[brush.size_space]
			"tip":
				return "" if not brush.tip else brush.tip.resource_path
			_:
				return brush.get(property)


func _ready() -> void:
	super._ready()
	set_properties([
		"Texture2D",
		Properties.FilePathProperty.new("tip"),
		Properties.FilePathProperty.new("texture"),
		Properties.ColorProperty.new("color"),
		Properties.BoolProperty.new("follow_path"),
		Properties.FloatProperty.new("spacing", 0, 1),
		Properties.FloatProperty.new("angle", 0, 1),
		"Flow/Opacity",
		Properties.FloatProperty.new("stroke_opacity", 0, 1),
		Properties.FloatProperty.new("flow", 0, 1),
		Properties.BoolProperty.new("flow_pen_pressure"),
		Properties.BoolProperty.new("size_pen_pressure"),
		"Randomness",
		Properties.FloatProperty.new("angle_jitter", 0, 1),
		Properties.FloatProperty.new("size_jitter", 0, 1),
		Properties.FloatProperty.new("position_jitter", 0, 1),
		"Symmetry",
		Properties.EnumProperty.new("symmetry", Brush.Symmetry.keys()),
		Properties.EnumProperty.new("symmetry_axis", SYMMETRY_AXIS.keys()),
		Properties.IntProperty.new("radial_symmetry_count", 2, 12),
		"Misc",
		Properties.EnumProperty.new("projection", Brush.BrushProjection.keys()),
		Properties.EnumProperty.new("size_space", Brush.SizeSpace.keys()),
		Properties.FilePathProperty.new("stencil"),
	])


func load_brush(brush : Brush) -> void:
	_editable_brush = EditableBrush.new(brush)
	load_values(_editable_brush)


func _on_property_changed(_property, _value) -> void:
	store_values(_editable_brush)