<?php

/** @noinspection PhpPossiblePolymorphicInvocationInspection */

namespace DefStudio\GameEngine\Decorators\Runs;

use Illuminate\Support\Collection;
use DefStudio\GameEngine\Models\Run;
use DefStudio\GameEngine\Models\Mission;
use DefStudio\GameEngine\Enums\MediaCollection;
use DefStudio\GameEngine\Decorators\ModelDecorator;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
use DefStudio\GameEngine\Decorators\Tasks\TaskDecorator;

/**
 * @extends ModelDecorator<Mission>
 *
 * @mixin Mission
 */
class PlayableMission extends ModelDecorator
{
    /** @var Collection<int, TaskDecorator> */
    public Collection $extracted_tasks;

    private Run $run;

    protected function setup_decorator(): void
    {
        $this->model->loadMissing(['media', 'storytellings', 'tasks']);
    }

    public function active(): bool
    {
        return isset($this->extracted_tasks);
    }

    public function setup(Run $run): self
    {
        $this->run = $run;

        if (($task_ids = $run->get_state("missions.$this->id.extracted_tasks")) !== null) {
            $this->extracted_tasks = Collect($task_ids)
                ->map(fn(int $task_id) => $this->tasks->firstOrFail(fn(TaskDecorator $task) => $task->id === $task_id));
        }

        return $this;
    }

    public function completed(): bool
    {
        return $this->run->get_state("missions.$this->id.completed", false);
    }

    public function all_tasks_completed(): bool
    {
        if (!$this->active()) {
            return false;
        }

        return $this->extracted_tasks->every(fn(TaskDecorator $task) => PlayableTask::build($task)->setup($this->run)->completed());
    }

    public function placeholder(): Media
    {
        return $this->getFirstMedia(MediaCollection::placeholder);
    }

    public function placeholder_complete(): Media|null
    {
        return $this->getFirstMedia(MediaCollection::placeholder_complete) ?? $this->getFirstMedia(MediaCollection::placeholder);
    }

    public function placeholder_active(): Media|null
    {
        return $this->getFirstMedia(MediaCollection::placeholder_active) ?? $this->getFirstMedia(MediaCollection::placeholder);
    }

    public function current_placeholder(): Media
    {
        if ($this->completed()) {
            return $this->placeholder_complete();
        }

        if ($this->active()) {
            return $this->placeholder_active();
        }

        return $this->placeholder();
    }

    public function visible(): bool
    {
        if ($this->should_hide_when_not_active() && !$this->active()) {
            return false;
        }

        if (!$this->should_hide_when_completed()) {
            return true;
        }

        return !$this->completed();
    }
}
