class_name BagItemSprite
extends ItemDragSource

signal drag_started
signal drag_finished

@onready var _visual_root: Control = %VisualRoot
@onready var _item_texture: TextureRect = %ItemTexture
@onready var _quantity_badge: PanelContainer = %QuantityBadge
@onready var _quantity_label: Label = %QuantityLabel
@onready var _compatibility_marker: Label = %CompatibilityMarker

var _motion_phase: float = 0.0
var _depth_scale: float = 1.0
var _selected: bool = false
var _hovered: bool = false
var _dragging: bool = false


func _ready() -> void:
	mouse_entered.connect(_set_hovered.bind(true))
	mouse_exited.connect(_set_hovered.bind(false))
	focus_entered.connect(_refresh_style)
	focus_exited.connect(_refresh_style)
	resized.connect(_update_visual_pivot)
	_update_visual_pivot()
	_apply_quantity_style()
	_refresh_style()


func configure_item(
	new_item_id: StringName,
	new_item_name: String,
	new_icon: Texture2D,
	quantity: int,
	hotbar_compatible: bool,
	phase: float,
	depth_scale: float,
) -> void:
	setup(new_item_id, new_item_name, new_icon)
	_item_texture.texture = new_icon
	_quantity_label.text = "×%d" % quantity
	_quantity_badge.visible = quantity > 1
	_compatibility_marker.visible = not hotbar_compatible
	_motion_phase = phase
	_depth_scale = depth_scale


func set_selected(selected: bool) -> void:
	_selected = selected
	_refresh_style()


func advance_presentation(elapsed: float, motion_enabled: bool) -> void:
	if not motion_enabled or _dragging:
		return
	var bob: float = sin(elapsed * TAU / 7.4 + _motion_phase) * 0.9
	var tilt: float = sin(
		elapsed * TAU / 10.2 + _motion_phase * 1.29
	) * 0.014
	_visual_root.position = Vector2(0.0, bob)
	_visual_root.rotation = tilt
	var emphasis: float = 1.04 if _hovered or has_focus() else 1.0
	_visual_root.scale = Vector2.ONE * _depth_scale * emphasis


func _get_drag_data(at_position: Vector2) -> Variant:
	var payload: Variant = super(at_position)
	if payload != null:
		_dragging = true
		drag_started.emit()
	return payload


func _notification(what: int) -> void:
	if what == NOTIFICATION_DRAG_END and _dragging:
		_dragging = false
		drag_finished.emit()


func _has_point(point: Vector2) -> bool:
	var radius: Vector2 = size * Vector2(0.46, 0.42)
	if radius.x <= 0.0 or radius.y <= 0.0:
		return false
	var normalized: Vector2 = (point - size * 0.5) / radius
	return normalized.length_squared() <= 1.0


func _set_hovered(hovered: bool) -> void:
	_hovered = hovered
	_refresh_style()


func _update_visual_pivot() -> void:
	_visual_root.pivot_offset = size * 0.5


func _refresh_style() -> void:
	var style := StyleBoxFlat.new()
	style.bg_color = (
		UtilityPageStyle.OCEAN_SELECTED
		if _selected else Color(UtilityPageStyle.OCEAN_FIELD, 0.48)
	)
	if _selected:
		style.bg_color = UtilityPageStyle.OCEAN_SELECTED
	if has_focus():
		style.bg_color = UtilityPageStyle.OCEAN_BUTTON_HOVER
	elif _hovered:
		style.bg_color = Color(UtilityPageStyle.OCEAN_PANEL_MID, 0.88)
	style.set_border_width_all(0)
	style.set_corner_radius_all(64)
	for state: StringName in [
		&"normal",
		&"hover",
		&"focus",
		&"pressed",
	]:
		add_theme_stylebox_override(state, style)


func _apply_quantity_style() -> void:
	var style := StyleBoxFlat.new()
	style.bg_color = UtilityPageStyle.OCEAN_SELECTED
	style.set_border_width_all(0)
	style.set_corner_radius_all(18)
	style.content_margin_left = 5.0
	style.content_margin_right = 5.0
	_quantity_badge.add_theme_stylebox_override("panel", style)
