extends VBoxContainer

# Copyright (c) 2019-2020 Péter Magyar
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

export(float) var max_distance : float = 70 setget set_max_distance
var max_distance_squared : float = max_distance * max_distance

export(NodePath) var name_label_path : NodePath = "Name"
export(NodePath) var health_bar_path : NodePath = "HealthBar"
export(NodePath) var health_bar_label_path : NodePath = "HealthBar"

export(Color) var normal_color : Color = Color("#e7e7e7")
export(Vector2) var normal_scale : Vector2 = Vector2(0.75, 0.75)
export(Color) var mouseover_color : Color = Color("#ffffff")
export(Vector2) var mouseover_scale : Vector2 = Vector2(0.85, 0.85)
export(Color) var targeted_color : Color = Color("#ffffff")
export(Vector2) var targeted_scale : Vector2 = Vector2(0.85, 0.85)

var target_scale : Vector2
var interpolating : bool

var targeted : bool = false

var name_label : Label = null
var health_bar : TextureProgress = null
var health_bar_label : Label = null

var entity : Entity = null
var entity_body : Node = null
var health : EntityResource = null

var _health : EntityResource

var body_visibility : bool = true

func _init():
	set_process(false)

func _enter_tree():
	name_label = get_node(name_label_path) as Label
	health_bar = get_node(health_bar_path) as TextureProgress
	health_bar_label = get_node(health_bar_label_path) as Label
	
	entity = get_node("../..") as Entity
	entity.connect("centity_resource_added", self, "on_centity_resource_added")
	entity_body = entity.get_body()

	name_label.text = entity.centity_name
	
	entity.connect("cname_changed", self, "cname_changed")
	entity.connect("notification_cmouse_entered", self, "onc_entity_mouse_entered")
	entity.connect("notification_cmouse_exited", self, "onc_entity_mouse_exited")
	entity.connect("notification_ctargeted", self, "notification_ctargeted")
	entity.connect("notification_cuntargeted", self, "notification_cuntargeted")
	entity.connect("body_changed", self, "_body_changed")
	
	modulate = normal_color
	set_scale(normal_scale)
	
	target_scale = normal_scale
	interpolating = false
	
	_on_body_visibility_changed()

func _process(delta):
	assert(body_visibility)
	
	if interpolating:
		var d : Vector2 = ((target_scale - get_scale()).normalized() * delta) + get_scale()
		
		set_scale(d)
		
		if (get_scale() - target_scale).length() < 0.01:
			interpolating = false

	
	var position : Vector3 = entity.get_transform_3d().origin
	
	var camera : Camera = get_tree().get_root().get_camera() as Camera
	
	if camera == null:
		return
	
	var cam_pos : Vector3 = camera.global_transform.xform(Vector3())
	var dstv : Vector3 = cam_pos - position
	dstv.y = 0
	var dst : float = dstv.length_squared()

	if dst > max_distance_squared:
		if visible:
			hide()
		return
		
	var cam_facing : Vector3 = -camera.global_transform.basis.z
	var d : float = cam_facing.dot(dstv)
		
	if d > 0:
		if visible:
			hide()
		return
	else:
		if not visible:
			show()
		
		
	position.y += 1.9
	var screen_position : Vector2 = camera.unproject_position(position)
	
	var new_pos : Vector2 = Vector2(screen_position.x - (rect_size.x / 2.0) * rect_scale.x, screen_position.y - (rect_size.y) * rect_scale.y)
	
	set_position(new_pos)

	
func set_max_distance(var value : float) -> void:
	max_distance_squared = value * value
	
	max_distance = value

func c_health_changed() -> void:
	if _health.max_value == 0:
		health_bar.max_value = 1
		health_bar.value = 0
		return
		
	health_bar.max_value = _health.max_value
	health_bar.value = _health.current_value
	
	
#	if stat.cmax != 0:
#		health_bar_label.text = str(int(stat.ccurrent / stat.cmax * 100))

func cname_changed(ent : Entity) -> void:
	name_label.text = ent.centity_name

func onc_entity_mouse_entered() -> void:
	if targeted:
		return
	
	modulate = mouseover_color
	interpolate_scale(mouseover_scale)
	
func onc_entity_mouse_exited() -> void:
	if targeted:
		return
	
	modulate = normal_color
	interpolate_scale(normal_scale)
	
func notification_ctargeted() -> void:
	targeted = true

	modulate = targeted_color
	interpolate_scale(targeted_scale)
	
func notification_cuntargeted() -> void:
	targeted = false
	
	modulate = normal_color
	interpolate_scale(normal_scale)

func interpolate_scale(target : Vector2) -> void:
	target_scale = target
	interpolating = true

func on_centity_resource_added(resorce) -> void:
	if health != null:
		return
	
	_health = entity.getc_health()
	_health.connect("changed", self, "c_health_changed")
	c_health_changed()

func _body_changed(ent):
	entity_body = entity.get_body()
	
	if entity_body && entity_body.has_signal("visibility_changed"):
		entity_body.connect("visibility_changed", self, "_on_body_visibility_changed")
	else:
		_on_body_visibility_changed()

func _on_body_visibility_changed():
	if entity_body:
		body_visibility = entity_body.visible
	else:
		body_visibility = true
	
	set_process(body_visibility)
