extends Node3D
class_name AstraBase

const ROOM_PART_SCENE := preload("res://stages/3d_scenes/astra_base/room_part.tscn")
const ROOM_END_SCENE := preload("res://stages/3d_scenes/astra_base/assets/3d/astra_base_room_end.blend")
const INCUBATOR_SCENE := preload("res://stages/3d_scenes/astra_base/incubator.tscn")
const ROOM_PART_SHIFT := 21.4
const INCUBATOR_BY_ROOM := 8
const INCUBATOR_DISTANCE := 4.22

const LIFT_TIME := 2

@export var room_part_number := 100 : set = set_room_part_number

var chosen_incubator_id := -1

# Cheat Code
# func _input(_e):
#     if (
#         Input.is_action_pressed("drop")
#         and Input.is_action_pressed("move_right")
#         and Input.is_action_pressed("move_left")
#         and Input.is_action_just_pressed("action")
#     ):
#         finish_scene()

# Called when the node enters the scene tree for the first time.
func _ready():
    if not Engine.is_editor_hint():
        Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
    set_room_part_number()

func spawn_player():
    chosen_incubator_id = randi_range(0, len(%Incubators.get_children()) - 1)
    var new_player_incubator := %Incubators.get_children()[chosen_incubator_id] as Incubator
    new_player_incubator.used = true
    %Player3D.position = new_player_incubator.global_position + Vector3.UP
    %Player3D.rotation = new_player_incubator.rotation
    %LiftPlayerDetector.body_entered.connect(
        func (b : Node3D):
            if b is Player3D:
                %Lift.interactable = true
    )

    GameInfo.game_data.incubator_used.append(chosen_incubator_id)

    story_on_spawn()


func story_on_spawn():
    AudioManager.play_sfx("Respawn")
    %LiftHideScreen.visible = false
    
    if (
        GameInfo.game_data.progression_data.get_story_step() is TutorialStoryStep
        and not TutorialStoryStep.INTRO_DIALOG in GameInfo.game_data.dialogs_done
    ):
        %Phone.visible = true
        %Phone.play_audio()
        await %Phone.clicked
        %Phone.stop_audio()
        %Phone.interactable = false

        Dialogic.start(TutorialStoryStep.INTRO_DIALOG)
        await Dialogic.timeline_ended
    else:
        %Phone.visible = false
        %Phone.position.y += 1000

    %LiftAnimationPlayer.play("arrive")
    AudioManager.play_sfx("Elevator")
    await %Lift.clicked
    %Player3D.controlling_player = false
    %Player3D.reparent(%Lift)
    %LiftAnimationPlayer.play_backwards("arrive")
    
    AudioManager.play_sfx("Elevator")

    await get_tree().create_timer(LIFT_TIME).timeout

    finish_scene()


func arrive_player():
    %LiftHideScreen.visible = true
    %Phone.visible = false
    %Phone.position.y += 1000
    %Player3D.position = %LiftPlayerDetector.global_position + Vector3.UP
    %Player3D.reparent(%Lift)
    %LiftAnimationPlayer.play("arrive")
    AudioManager.play_sfx("Elevator")

    %AstraDoor.interactable = true

func finish_scene():
    GameInfo.game_data.start_run()
    if GameInfo.game_data.progression_data.get_story_step() is TutorialStoryStep:
        GameInfo.game_data.current_run.choose_next_run_point()
        SceneManager.change_to_scene(RegionScene.new(GameInfo.game_data.current_region_data))
    else:
        SceneManager.change_to_scene(CockpitScene.new())


func set_room_part_number(_room_part_number : int = room_part_number):
    room_part_number = _room_part_number
    if is_node_ready():
        for c in %RoomParts.get_children():
            c.queue_free()
        for c in %Incubators.get_children():
            c.queue_free()
        
        var shifted_origin = Vector3.LEFT * ROOM_PART_SHIFT * room_part_number/2
        
        var incubator_id = 0
        for i in range(room_part_number):
            var new_room_part := ROOM_PART_SCENE.instantiate() as Node3D
            %RoomParts.add_child(new_room_part)
            new_room_part.position = Vector3.LEFT * ROOM_PART_SHIFT * i - shifted_origin
            for j in range(INCUBATOR_BY_ROOM):
                for direction in [-1, 1]:
                    var new_incubator := INCUBATOR_SCENE.instantiate() as Incubator
                    new_incubator.used = incubator_id in GameInfo.game_data.incubator_used
                    %Incubators.add_child(new_incubator)
                    incubator_id += 1
                    new_incubator.position = (
                        new_room_part.position 
                        + j * Vector3.LEFT * (ROOM_PART_SHIFT / INCUBATOR_BY_ROOM) 
                        - Vector3.LEFT * ROOM_PART_SHIFT / 2
                        - Vector3.RIGHT / 2
                        + Vector3.FORWARD * direction * INCUBATOR_DISTANCE
                    )
                    if direction == 1:
                        new_incubator.rotate(Vector3.UP,PI)

        
        for i in [-1,room_part_number]:
            var new_room_end := ROOM_END_SCENE.instantiate() as Node3D
            %RoomParts.add_child(new_room_end)
            new_room_end.position = Vector3.LEFT * ROOM_PART_SHIFT * i - shifted_origin
