<?php

namespace App\Livewire;

use App\Models\Game;
use App\Models\Genre;
use App\Models\Platform;
use Illuminate\View\View;
use Livewire\Component;

/**
 * Game Selector for existing games and new games.
 */
class GameSelector extends Component
{

    public const int REQUIRED_CHARS = 3;

    /**
     * Which section we can change selection mode.
     */
    public const array CHANGE_SECTION_MODE = [ 'utilities', 'documents' ];

    /**
     * Selection mode between game|platform|none.
     * @var string
     */
    public string $selectionMode = 'game';

    /**
     * If we are in new game mode.
     * @var bool
     */
    public bool $newGame = false;

    /**
     * Current user game search.
     * @var string
     */
    public string $search = '';

    /**
     * Existing game ID selected.
     * @var int|null
     */
    public ?int $gameId = null;

    /**
     * Existing game name selected or new game name.
     * @var string|null
     */
    public ?string $gameName = null;

    /**
     * New game platform ID.
     * @var int|null
     */
    public ?int $gamePlatformId = null;

    /**
     * New game genre ID.
     * @var int|null
     */
    public ?int $gameGenreId = null;

    /**
     * Existing game platform name or new game platform name.
     * @var string|null
     */
    public ?string $platformName = null;

    /**
     * Existing game genre name or new game genre name.
     * @var string|null
     */
    public ?string $genreName = null;

    /**
     * If dropdown must be rendered or not.
     * @var bool
     */
    public bool $dropdown = false;

    /**
     * In platform mode.
     * @var int|null
     */
    public ?int $platformModeId = null;

    /**
     * In platform mode.
     * @var string|null
     */
    public ?string $platformModeName = null;

    public ?string $section = null;

    public function mount( ?int $gameId = null, ?string $newGameTitle = null, ?int $newGamePlatform = null, ?int $newGameGenre = null, ?string $section, ?int $platformOnlyId ): void
    {

        $this->section = $section;

        // If we selected an existent game.
        if( $gameId ){
            $game = Game::with(['platform','genre'])->find($gameId);
            if( $game ){
                $this->gameId = $game->id;
                $this->gameName = $game->name;
                $this->platformName = $game->platform->name;
                $this->genreName = $game->genre->name;
                $this->search = $game->name;
                $this->newGame = false;
                return;
            }
        }

        if( $newGameTitle || $newGamePlatform || $newGameGenre ){
            $this->newGame = true;
            $this->gameName = $newGameTitle;
            $this->gamePlatformId = is_numeric($newGamePlatform) ? (int) $newGamePlatform : null;
            $this->gameGenreId = is_numeric($newGameGenre) ? (int) $newGameGenre : null;
        }

        if( in_array( $section, self::CHANGE_SECTION_MODE ) ) {
            if ($platformOnlyId) {
                $this->selectionMode = 'platform';
                $this->platformModeId = $platformOnlyId;
                $platform = Platform::find($platformOnlyId);
                if ($platform) {
                    $this->platformModeName = $platform->name;
                } else {
                    $this->platformModeId = null;
                }
            }
        }
    }

    public function setSelectionMode(string $mode): void
    {
        if( !in_array( $this->section, self::CHANGE_SECTION_MODE ) )
            return;

        $this->selectionMode = $mode;

        if( $mode !== 'game' ){
            $this->clearGame();
            $this->newGame = false;
        }
        if( $mode !== 'platform' ){
            $this->platformModeId = null;
            $this->platformModeName = null;
        }
    }

    /**
     * If we update search bar.
     * @return void
     */
    public function updatedSearch(): void
    {
        if( $this->gameId ){
            $this->gameId = null;
            $this->gameName = null;
            $this->platformName = null;
            $this->genreName = null;
        }
        $this->dropdown = strlen($this->search) >= self::REQUIRED_CHARS;
    }

    /**
     * Select an existent game.
     *
     * @param int $id
     * @param string $name
     *
     * @return void
     */
    public function selectGame( int $id, string $name ): void
    {
        $game = Game::with(['platform','genre'])->find($id);
        if( $game ){
            $this->gameId = $game->id;
            $this->gameName = $game->name;
            $this->platformName = $game->platform->name;
            $this->genreName = $game->genre->name;
            $this->search = $game->name;
            $this->dropdown = false;

            $this->dispatch( 'game-selected', id: $id ); // Send an event to the JS part.
        }

    }

    public function selectPlatformOnly( int $id ): void
    {
        $platform = Platform::find($id);
        if( $platform ){
            $this->platformModeId = $platform->id;
            $this->platformModeName = $platform->name;
        }
    }

    /**
     * Clear existent game selection.
     * @return void
     */
    public function clearGame(): void
    {
        $this->gameId = null;
        $this->gameName = null;
        $this->platformName = null;
        $this->genreName = null;
        $this->search = '';

        $this->dispatch( 'game-selected', id: null ); // Send an event to the JS part.
    }

    /**
     * Switch mode.
     * @return void
     */
    public function switchNewGame(): void
    {
        $this->clearGame();
        $this->newGame = !$this->newGame;
    }

    public function render(): View
    {
        $games = collect();

        // Need to search games for dropdown.
        if( $this->dropdown && strlen($this->search) >= self::REQUIRED_CHARS && $this->newGame === false ){
            $games = Game::with(['platform','genre'])
                ->where('name', 'like', '%'.$this->search.'%')
                ->orderBy('name')
                ->limit(20)
                ->get();
        }

        $data = [ 'games' => $games, 'required_chars' => self::REQUIRED_CHARS ];
        if( $this->newGame === true ){ // If we want a new game, get platforms and genres.
            $data['platforms'] = Platform::orderBy('name')->get();
            $data['genres'] = Genre::orderBy('name')->get();
        }
        $data['hasOldNewGame'] = old('new-game-title') || old('new-game-platform') || old('new-game-genre');

        $data['canChangeSelection'] = in_array( $this->section, self::CHANGE_SECTION_MODE );
        if( in_array( $this->section, self::CHANGE_SECTION_MODE ) )
            $data['platforms'] = Platform::orderBy('name')->get();

        return view('livewire.game-selector', $data );
    }
}
