<?php


namespace App\Model\Facades\Writers;


use App\Model\Entities\GameData\Mmorpg\Race;
use App\Model\Facades\Readers\FactionReader;
use App\Model\Facades\Readers\GameReader;
use App\Model\Facades\Readers\RaceReader;
use App\Model\Services\RaceService;
use Throwable;

class RaceWriter extends BaseWriter
{
    /** @var  RaceService */
    protected $raceService;
    /** @var  RaceReader */
    protected $raceReader;
    /** @var  GameReader */
    protected $gameReader;
    /** @var  FactionReader */
    protected $factionReader;

    public function inject(RaceService $raceService, RaceReader $raceReader,
                           GameReader $gameReader, FactionReader $factionReader)
    {
        $this->raceService = $raceService;
        $this->raceReader = $raceReader;
        $this->gameReader = $gameReader;
        $this->factionReader = $factionReader;
    }

    public function createRace($game, string $name, array $factions = array()) : Race
    {
        $gameEntity = $this->gameReader->validateGame($game);

        try {
            $this->beginTransaction();
            $race = $this->raceService->createRace($this->getLoggedInUser(), $gameEntity, $name);
            foreach ($factions as $faction) {
                $this->makeRaceAvailableToFaction($race, $faction);
            }
            $this->commit();
        } catch (Throwable $e) {
            $this->rollback();
            throw $e;
        }

        return $race;
    }

    public function editName($race, string $newName)
    {
        $raceEntity = $this->raceReader->validateRace($race);

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

    /**
     * @param $race
     * @param $faction
     * @throws Throwable
     */
    public function makeRaceAvailableToFaction($race, $faction)
    {
        $raceEntity = $this->raceReader->validateRace($race);
        $factionEntity = $this->factionReader->validateFaction($faction);

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

    /**
     * @param $race
     * @param $faction
     * @throws Throwable
     */
    public function makeRaceUnavailableToFaction($race, $faction)
    {
        $raceEntity = $this->raceReader->validateRace($race);
        $factionEntity = $this->factionReader->validateFaction($faction);

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