<?php

/** @noinspection LaravelUnknownEloquentFactoryInspection */

namespace DefStudio\GameEngine\Models;

use Spatie\MediaLibrary\HasMedia;
use Illuminate\Support\Collection;
use Illuminate\Database\Eloquent\Model;
use DefStudio\GameEngine\Enums\MediaCollection;
use DefStudio\GameEngine\Attributes\ParentScope;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use DefStudio\GameEngine\Models\Contracts\FitsInScope;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use DefStudio\GameEngine\Models\Concerns\DefinesAwards;
use DefStudio\GameEngine\Decorators\Tasks\TaskDecorator;
use DefStudio\GameEngine\Models\Concerns\BelongsToScope;
use DefStudio\GameEngine\Models\Contracts\AwardsDefiner;
use DefStudio\GameEngine\Models\Concerns\HasStorytellings;
use DefStudio\GameEngine\Database\Factories\MissionFactory;
use DefStudio\GameEngine\Models\Contracts\WithStorytelling;
use function game_engine;

/**
 * @property int $id;
 * @property int $map_id;
 * @property string $title;
 * @property string $description;
 * @property int $pos_x;
 * @property int $pos_y;
 * @property int $order;
 * @property array $configuration;
 * @property-read Map $map,
 * @property-read Collection<int, TaskDecorator> $tasks
 *
 * @method static MissionFactory factory(array|callable|int|null $count = null, array|callable $state = [])
 */
class Mission extends Model implements HasMedia, WithStorytelling, FitsInScope, AwardsDefiner
{
    use HasFactory;
    use Concerns\HasMedia;
    use HasStorytellings;
    use BelongsToScope;
    use DefinesAwards;

    protected $fillable = [
        'title',
        'description',
        'pos_x',
        'pos_y',
        'order',
    ];

    protected $casts = [
        'pos_x' => 'integer',
        'pos_y' => 'integer',
        'order' => 'integer',
        'configuration' => AsArrayObject::class,
    ];

    protected $attributes = [
        'configuration' => '{}',
    ];

    protected array $media_collections = [
        MediaCollection::placeholder,
        MediaCollection::cover,
    ];

    public function getTable()
    {
        return config('game-engine.missions.table', parent::getTable());
    }

    protected static function newFactory(): MissionFactory
    {
        return MissionFactory::new();
    }

    /**
     * @return BelongsTo<Map, Mission>
     */
    #[ParentScope(Map::class)]
    public function map(): BelongsTo
    {
        return $this->belongsTo(game_engine()->mapClass());
    }

    public function tasks(): HasMany
    {
        return $this->hasMany(game_engine()->taskClass());
    }

    /**
     * @return Collection<int, TaskDecorator>
     *
     * @noinspection PhpUnused
     */
    public function getTasksAttribute(): Collection
    {
        return $this->getRelationValue('tasks')
            ->map(fn(Task $task): TaskDecorator => $task->decorate());
    }

    public function award_scope_label(): string
    {
        return __('Mission: :mission_title', ['mission_title' => $this->title]);
    }

    public function max_tasks_to_show(): int|null
    {
        return $this->configuration['max_tasks_to_show'] ?? null;
    }

    public function should_randomize_tasks_order(): bool
    {
        return $this->configuration['randomize_tasks_order'] ?? false;
    }

    public function should_hide_when_not_active(): bool
    {
        return $this->configuration['hide_when_not_active'] ?? false;
    }

    public function should_hide_when_completed(): bool
    {
        return $this->configuration['hide_when_completed'] ?? false;
    }

    public function should_complete_on_activation(): bool
    {
        return $this->configuration['complete_on_activation'] ?? false;
    }
}
