extends Control

##TODO
# 2. Fix reset buttons
# 3. Fix settings
# 4. Fix top buttons
# 5. Fix player name
# 7. Fix welcome into the game
# 8. Fix match ball sound
# 9. Fix winner
# 10. Fix jump between songs
# 11. Refactor components
# 12. Change add player
# 13. Fix graphics in lists
# 14. Fix layout
# 15. Fix for local play
# 16. Change all calls to make_request and function in function
# 17. Change some buttons to icons

@onready
var open_button := $Open

@onready
var fileDialog := $FileDialog

@onready
var insperation_scroll := $ScrollContainer

@onready
var insperation_list := $ScrollContainer/VBoxContainer

@onready
var game_label := $VBoxContainer/GameLabel

@onready
var song_label := $VBoxContainer/SongLabel

@onready
var play_button := $PanelContainer/HBoxContainer/PlayButton

@onready
var stop_button := $PanelContainer/HBoxContainer/StopButton

@onready
var audio := $AudioStreamPlayer

@onready
var progress := $PanelContainer/HBoxContainer/HSlider

@onready
var label := $PanelContainer/HBoxContainer/Label

@onready
var add_player := $Players/VBoxContainer/HBoxContainer/AddPlayer

@onready
var sound_test_button := $SoundTestButton

@onready
var sync_button := $SyncButton

@onready
var sync_popup := $PopupPanel

@onready
var show_answer_button := $ShowAnswerButton

@onready
var next_button := $NextButton

@onready
var music_list_scroll := $MusicListPanel/ScrollContainer

@onready
var music_list := $MusicListPanel/ScrollContainer/MusicList

@onready
var players := $Players/VBoxContainer

@onready
var character_select := $CharacterSelect

@onready
var search_button := $SearchButton

@onready
var search_view := $Search

var Player := preload("res://Player.tscn")

@onready
var path = '/Users/sebastian/ResilioSync/Sorterat_test/Metal Gear Solid 4 - Guns of the Patriots/2-16 Metal Gear Saga.mp3'

# Called when the node enters the scene tree for the first time.
func _ready():
	next_button.pressed.connect(fetch_next_song)
	play_button.pressed.connect(play_or_pause)
	stop_button.pressed.connect(stop)
	show_answer_button.pressed.connect(show_answer)
	search_button.pressed.connect(show_search)
	sync_button.pressed.connect(sync_games)
	sound_test_button.pressed.connect(get_sound_test_song)
	
	progress.drag_started.connect(_on_drag_started)
	progress.drag_ended.connect(_on_drag_ended)
	character_select.connect("character_selected", _on_character_selected)
	
	add_player.pressed.connect(add_players)
	
	open_button.pressed.connect(open)
	get_suggestion_list()
	
func get_sound_test_song():
	var play_sound_test_song = func(result, response_code, headers, body):
		if result != HTTPRequest.RESULT_SUCCESS:
			push_error("Song couldn't be downloaded. Try a different song.")
		var sound = AudioStreamMP3.new()
		sound.data = body
		audio.stream = sound
		audio.play()
		stream = audio.stream
		progress.max_value = round(stream.get_length())
		progress.tick_count = round(stream.get_length() / 60)
		
	make_request("https://music.sanplex.tech/music/first", play_sound_test_song)

func sound_test_local():
	path = "res://01. Opening.mp3"
	audio.stream = load_mp3(path)
	audio.play()
	stream = audio.stream
	progress.max_value = round(stream.get_length())
	progress.tick_count = round(stream.get_length() / 60)
	
func sync_games():
	var http_request = HTTPRequest.new()
	add_child(http_request)
	http_request.request_completed.connect(games_synced)
	
	# Perform a GET request. The URL below returns JSON as of writing.
	var error = http_request.request("https://music.sanplex.tech/sync")
	if error != OK:
		push_error("An error occurred in the HTTP request.")
		
func games_synced(result, response_code, headers, body):
	if response_code == 200:
		sync_popup.visible = true

func get_suggestion_list() -> void:
	var http_request = HTTPRequest.new()
	add_child(http_request)
	http_request.request_completed.connect(_http_request_completed)
	
	# Perform a GET request. The URL below returns JSON as of writing.
	var error = http_request.request("https://music.sanplex.tech/music/all")
	if error != OK:
		push_error("An error occurred in the HTTP request.")

func add_players():
	var new_player := Player.instantiate()
	players.add_child(new_player)
	new_player.connect("change_character_clicked", _on_player_change_character_clicked.bind(new_player))

func show_search():
	if search_view.visible == false:
		search_view.visible = true
	else:
		search_view.visible = false

func show_answer():
	var http_request = HTTPRequest.new()
	add_child(http_request)
	http_request.request_completed.connect(show_fetched)
	
	# Perform a GET request. The URL below returns JSON as of writing.
	var error = http_request.request("https://music.sanplex.tech/music/info")
	if error != OK:
		push_error("An error occurred in the HTTP request.")
	
func fetched():
	var http_request2 = HTTPRequest.new()
	add_child(http_request2)
	http_request2.request_completed.connect(show_fetched_list)
	
	# Perform a GET request. The URL below returns JSON as of writing.
	var error2 = http_request2.request("https://music.sanplex.tech/music/list")
	if error2 != OK:
		push_error("An error occurred in the HTTP request.")
	

var next_label: Label
func show_fetched(result, response_code, headers, body) -> void:
	var json = JSON.new()
	var error = json.parse(body.get_string_from_utf8())
	
	if error == OK:
		var data_received = json.get_data()
		print("data_received: ", data_received)
		game_label.text = data_received.Game
		song_label.text = data_received.Song
		var format_string = "%d. %s - %s"
		var actual_string = format_string % [(data_received.SongNo+1), data_received.Game, data_received.Song]
		next_label.text = actual_string
		
var song_list = []
func show_fetched_list(result, response_code, headers, body) -> void:
	var json = JSON.new()
	var error = json.parse(body.get_string_from_utf8())
	
	if error == OK:
		var data_received = json.get_data()
		if typeof(data_received) == TYPE_ARRAY:
			song_list = []
			song_list.append_array(data_received)
			delete_children(music_list)
			song_list.remove_at(song_list.size() - 1)
			for song in song_list:
				var label := Label.new()
				var format_string = "%d. %s - %s"
				var actual_string = format_string % [(song.SongNo+1), song.Game, song.Song]
				label.text = actual_string
				label.mouse_filter = Control.MOUSE_FILTER_PASS
				label.gui_input.connect(song_clicked.bind(song.SongNo))
				music_list.add_child(label)
				
			next_label = Label.new()
			next_label.text = "??? - ???"
			next_label.mouse_filter = Control.MOUSE_FILTER_PASS
			next_label.gui_input.connect(show_fetched)
			music_list.add_child(next_label)
			
		else:
			print("Unexpected data")

func song_clicked(event, song_no):
	if (event is InputEventMouseButton && event.pressed && event.button_index == MOUSE_BUTTON_LEFT):
		print("Clicked: " + str(song_no))

# Called when the HTTP request is completed.
func _http_request_completed(result, response_code, headers, body):
	var json = JSON.new()
	var error = json.parse(body.get_string_from_utf8())
	
	if error == OK:
		var data_received = json.get_data()
		if typeof(data_received) == TYPE_ARRAY:
			games.append_array(data_received)
			for game in games:
				var label := Label.new()
				label.text = game
				label.autowrap_mode = TextServer.AUTOWRAP_WORD
				insperation_list.add_child(label)
			insperation_scroll.scroll_to_bottom()
		else:
			print("Unexpected data")


	# Will print the user agent string used by the HTTPRequest node (as recognized by httpbin.org).
	#print(response)

func open():
	fileDialog.popup()



# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	if audio.has_stream_playback() && !is_changing && !audio.stream_paused:
		progress.value = audio.get_playback_position()
		label.text = format_text(progress.value, stream.get_length())	

func _on_file_dialog_dir_selected(path):
	print(path)
	dir_contents(path)
	
var songs := []
var games := []
#var player = preload("res://Player.gd")
	
func dir_contents(path: String) -> void:
	var dir = DirAccess.open(path)
	if dir:
		dir.list_dir_begin()
		var file_name = dir.get_next()
		songs.clear()
		while file_name != "":
			if dir.current_is_dir():
				#print("Found directory: " + file_name)
				games.append(file_name)
			else:
				#print("Found file: " + file_name)
				if file_name.ends_with(".mp3"):
					songs.append(path + "/" + file_name)
			file_name = dir.get_next()
		
	else:
		print("An error occurred when trying to access the path.")
	
	for game in games:
		var label := Label.new()
		label.text = game
		insperation_list.add_child(label)





var is_changing: bool = false
var playback_position: float
var stream: AudioStream

func set_songs(new_songs) -> void:
	songs = new_songs
	
func make_request(address, func_name) -> void:
	var http_request = HTTPRequest.new()
	add_child(http_request)
	http_request.request_completed.connect(func_name)
	
	# Perform a GET request. The URL below returns JSON as of writing.
	var error = http_request.request(address)
	if error != OK:
		push_error("An error occurred in the HTTP request.")
	

func format_time(time: float) -> String:
	var mins: String = "%02d" % floor(time / 60)
	var sec: String = "%02d" % round(fmod(time, 60))
	return  mins + ":" + sec
	
func format_text(part: float, total: float) -> String:	
	return format_time(part) + " / " + format_time(total)


func fetch_next_song() -> void:
	var http_request = HTTPRequest.new()
	add_child(http_request)
	#http.set_download_file("https://music.sanplex.tech/music/first")
	http_request.request_completed.connect(first_song_fetched)
	
	# Perform a GET request. The URL below returns JSON as of writing.
	var error = http_request.request("https://music.sanplex.tech/music/rand")
	if error != OK:
		push_error("An error occurred in the HTTP request.")

func first_song_fetched(result, response_code, headers, body) -> void:
	game_label.text = "????????"
	song_label.text = "??????"
	
	if result != HTTPRequest.RESULT_SUCCESS:
		push_error("Song couldn't be downloaded. Try a different song.")
	var sound = AudioStreamMP3.new()
	sound.data = body
	make_request("https://music.sanplex.tech/music/addQue", add_que)
	print("play given song")
	audio.stream = sound
	audio.play()
	stream = audio.stream
	progress.max_value = round(stream.get_length())
	progress.tick_count = round(stream.get_length() / 60)
	
func add_que(result, response_code, headers, body) -> void:
	print("response_code", response_code)
	fetched()

func play_local_song(song) -> void:
	if songs:
		path = songs[0]
		print(path)
		print(FileAccess.file_exists(path))
		audio.stream = load_mp3(path)
		print("play")
		audio.play()
		stream = audio.stream
		progress.max_value = round(stream.get_length())
		progress.tick_count = round(stream.get_length() / 60)

var is_paused: bool = true
func play_or_pause():
	if is_paused:
		is_paused = false
		play_button.text = "Pause"
		if audio.stream_paused:
			audio.stream_paused = false
			audio.seek(playback_position)
			print("continue")
			progress.max_value = round(stream.get_length())
			progress.tick_count = round(stream.get_length() / 60)
		else:
			fetch_next_song()
	else:
		audio.stream_paused = true
		playback_position = audio.get_playback_position()
		is_paused = true
		play_button.text = "Play"
	
func stop() -> void:
	audio.stop()
	audio.stream_paused = false
	progress.value = 0
	is_paused = true
	play_button.text = "Play"

func _on_drag_started() -> void:
	is_changing = true

func _on_drag_ended(_changed) -> void:
	audio.seek(progress.value)
	playback_position = progress.value
	is_changing = false

func load_mp3(_path) -> AudioStream:
	var file = FileAccess.open(_path, FileAccess.READ)
	var sound = AudioStreamMP3.new()
	sound.data = file.get_buffer(file.get_length())
	return sound

var current_player
func _on_player_change_character_clicked(new_player):
	print("_on_player_change_character_clicked")
	current_player = new_player
	character_select.visible = true

func _on_character_selected(file_name: String):
	print("_on_character_selected")
	character_select.visible = false
	current_player._on_control_character_selected_clicked(file_name)


static func delete_children(node):
	for n in node.get_children():
		node.remove_child(n)
		n.queue_free()
