<?php

namespace DefStudio\GameEngine\Http\Livewire\Maps;

use Livewire\Component;
use Illuminate\Contracts\View\View;
use DefStudio\GameEngine\Models\Map;
use DefStudio\GameEngine\Enums\MediaCollection;
use DefStudio\GameEngine\DTO\Missions\Placeholder;
use DefStudio\GameEngine\Actions\Missions\CreateMission;
use DefStudio\GameEngine\Actions\Missions\DeleteMission;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use DefStudio\GameEngine\Actions\Maps\GetMissionPlaceholders;
use DefStudio\GameEngine\Actions\Livewire\Sortable\UpdateOrder;
use DefStudio\GameEngine\Actions\Missions\UpdateMissionFromPlaceholder;

class Editor extends Component
{
    use AuthorizesRequests;

    protected $listeners = [
        'mission.updated' => 'refresh_mission_placeholders',
    ];

    /** @var Map */
    public $map;

    /** @var array<int, Placeholder> */
    public array $mission_placeholders = [];

    public function mount(): void
    {
        $this->authorize('save', $this->map);

        $this->refresh_mission_placeholders();
    }

    public function render(): View
    {
        return view('game-engine::livewire.admin.maps.editor');
    }

    public function getBackgroundImageUrlProperty(): string
    {
        return $this->map->getFirstMediaUrl(MediaCollection::background);
    }

    public function add_mission(): void
    {
        $mission = CreateMission::run($this->map);

        $this->refresh_mission_placeholders();

        $this->emit('openModal', 'game-engine.admin.missions.edit', ['isModal' => true, 'mission_id' => $mission->id]);
    }

    public function delete_mission(int $mission_id): void
    {
        $mission = $this->map->missions()->findOrFail($mission_id);
        DeleteMission::run($mission);

        $this->refresh_mission_placeholders();
    }

    public function updatedMissionPlaceholders($new_data): void
    {
        collect($new_data)
            ->mapInto(Placeholder::class)
            ->filter(function(Placeholder $placeholder): bool {
                $mission = $this->map->missions()->with('map')->find($placeholder->id);

                return UpdateMissionFromPlaceholder::run($mission, $placeholder);
            })->each(fn(Placeholder $placeholder) => $this->emit('mission.updated', $placeholder->id));

        $this->refresh_mission_placeholders();
    }

    public function refresh_mission_placeholders(): void
    {
        $this->map->unsetRelation('missions');
        $this->mission_placeholders = GetMissionPlaceholders::run($this->map)->toArray();
    }

    public function update_missions_order(array $new_order): void
    {
        UpdateOrder::run($this->map->missions, $new_order);
    }
}
