<?php


namespace App\Model\Facades\Writers;


use App\Model\Entities\GameData\Mmorpg\CharacterClass;
use App\Model\Facades\Readers\CharacterClassReader;
use App\Model\Facades\Readers\FactionReader;
use App\Model\Facades\Readers\GameReader;
use App\Model\Services\CharacterClassesService;
use Throwable;

class CharacterClassWriter extends BaseWriter
{
    /** @var  CharacterClassesService */
    protected $characterClassesService;
    /** @var  GameReader */
    protected $gameReader;
    /** @var  CharacterClassReader */
    protected $characterClassReader;
    /** @var  FactionReader */
    protected $factionReader;


    public function inject(CharacterClassesService $characterClassesService, GameReader $gameReader,
                           CharacterClassReader $characterClassReader, FactionReader $factionReader)
    {
        $this->characterClassesService = $characterClassesService;
        $this->gameReader = $gameReader;
        $this->characterClassReader = $characterClassReader;
        $this->factionReader = $factionReader;
    }

    /**
     * @param $game
     * @param string $name
     * @param array $factions
     * @return CharacterClass
     * @throws Throwable
     */
    public function createClass($game, string $name, array $factions = array()) : CharacterClass
    {
        $gameEntity = $this->gameReader->validateGame($game);

        try {
            $this->beginTransaction();
            $characterClass = $this->characterClassesService->createClass($this->getLoggedInUser(), $gameEntity, $name);
            foreach ($factions as $faction) {
                $this->makeCharacterClassAvailableToFaction($characterClass, $faction);
            }
            $this->commit();
        } catch (Throwable $e) {
            $this->rollback();
            throw $e;
        }

        return $characterClass;
    }

    /**
     * @param $class
     * @param $faction
     * @throws Throwable
     */
    public function makeCharacterClassAvailableToFaction($class, $faction)
    {
        $characterClassEntity = $this->characterClassReader->validateCharacterClass($class);
        $factionEntity = $this->factionReader->validateFaction($faction);

        try {
            $this->beginTransaction();
            $factionEntity->addCharacterClass($characterClassEntity);
            $this->commit();
        } catch (Throwable $e) {
            $this->rollback();
            throw $e;
        }
    }

    /**
     * @param $class
     * @param $faction
     * @throws Throwable
     */
    public function makeCharacterClassUnavailableToFaction($class, $faction)
    {
        $characterClassEntity = $this->characterClassReader->validateCharacterClass($class);
        $factionEntity = $this->factionReader->validateFaction($faction);

        try {
            $this->beginTransaction();
            $factionEntity->removeCharacterClass($characterClassEntity);
            $this->commit();
        } catch (Throwable $e) {
            $this->rollback();
            throw $e;
        }
    }

    public function editName($class, $newName)
    {
        $classEntity = $this->characterClassReader->validateCharacterClass($class);

        try {
            $this->beginTransaction();
            $classEntity->setName($newName);
            $classEntity->setEditedBy($this->getLoggedInUser());
            $this->commit();
        } catch (Throwable $e) {
            $this->rollback();
            throw $e;
        }
    }
}