extends RigidBody3D

@export_group("Buyancy")
@export var float_force := 40
@export var water_drag:= 0.05
@export var water_angular_drag := 0.05
@export var WaterNode:MeshInstance3D
@export var ripple_texture: Texture2D
@export var upforce_max := 500.0

@export_group("Inputs")
@export var acceleration := 10  # Forward force
@export var turn_speed := 2.0  # Rotation speed
@export var max_speed := 60.0  # Limit speed
## Slow down naturally
@export var water_resistance := 0.98  

@onready var gravity:float = ProjectSettings.get_setting("physics/3d/default_gravity")

###### Buyancy ########
var cells_scale: Vector2 = Vector2(1.0, 1.0)  # Same as `CellsScale`
var max_ripple_height: float = 1.0  # Same as `MaxRippleHeight`
var Wantedheight: float = 1.0  # Same as `MaxRippleHeight`
var ripple: Vector2  # Same as `MaxRippleHeight`
var noise: FastNoiseLite
var InputForce:Vector3

var water_height :=0.0
var inWater := false

# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	var material
	if WaterNode != null:
		material = WaterNode.mesh.surface_get_material(0)
		noise = load("res://mat/wavenoise.tres").noise
	if material != null:
		cells_scale = material.get_shader_parameter("CellsScale")
		ripple = material.get_shader_parameter("RippleTimeScale")
		max_ripple_height = material.get_shader_parameter("MaxRippleHeight")
		ripple_texture = load("res://mat/wavenoise.tres")
	pass # Replace with function body.


	

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	
	  # Get input directions
	var forward_input = Input.get_action_strength("move_forward") - Input.get_action_strength("move_backward")
	var turn_input = Input.get_action_strength("turn_right") - Input.get_action_strength("turn_left")

	# Apply forward force in the boat's local forward direction
	var forward_vector = global_transform.basis.x  # Local forward direction
	var direction = forward_vector * forward_input * acceleration 
	InputForce = direction
	
		
	print (InputForce)
	apply_central_force(InputForce)
	
	
func _physics_process(_delta: float) -> void:
	water_height = get_water_height(global_position)

	var currentDepth = water_height - global_position.y
	

	if currentDepth > 0:
		inWater = true
		var force_to_apply:Vector3 = Vector3.UP * clamp(float_force * gravity * currentDepth,0.0,upforce_max)

		apply_central_force(force_to_apply)
		var water_tilt = get_water_normal()
		# Get current rotation
		var current_rotation = $untitled.rotation

	# Smoothly interpolate rotation to match water tilt
		current_rotation.x = lerp_angle(current_rotation.x, water_tilt.x, 0.25)  # Smooth pitch
		current_rotation.z = lerp_angle(current_rotation.z, water_tilt.z, 0.25)  # Smooth roll

		$untitled.rotation = current_rotation  # Apply the new rotation
		
	else:
		inWater = false
	
	
	
func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
	# Change comportement based on if in water or not
	if inWater:
		state.linear_velocity *= 1 - water_drag
		state.angular_velocity *= 1 - water_angular_drag
	
	
	
	
func get_water_height(_position:Vector3) -> float:
	var wave_speed = 15.0
	# Step 1: Compute noise-based wave height
	var uv = Vector2(_position.x, _position.z) * cells_scale  # Matches shader scaling

	# Step 2: Apply time-based animation for moving waves
	var time_offset = Time.get_ticks_msec() * 0.001 * wave_speed
	var noise_value = noise.get_noise_2d(uv.x + time_offset, uv.y + time_offset)  # Noise-based wave

	# Step 3: Scale and return final water height
	return 0.15 + (noise_value *  max_ripple_height)
	
func get_water_normal() -> Vector3:
	var offset = 1.0  # Distance for sampling points (adjust as needed)

	# Sample water height at three nearby points
	var p1 = global_position + Vector3(offset, 0, 0)  # Right side
	var p2 = global_position + Vector3(0, 0, offset)  # Forward side

	var h1 = get_water_height(p1)  # Height at right side
	var h2 = get_water_height(p2)  # Height at forward side
	var h_center = get_water_height(global_position)  # Center height

	# Calculate tilt angles
	var pitch = atan2(h2 - h_center, offset)  # Forward/backward tilt (X-axis)
	var roll = atan2(h1 - h_center, offset)   # Left/right tilt (Z-axis)

	return Vector3(pitch, 0, roll)  # Euler angles (X: pitch, Y: unused, Z: roll)
