<?php


namespace App\Model\Facades\Writers;


use App\Model\Entities\Components\News\News;
use App\Model\Entities\Components\News\NewsContainer;
use App\Model\Facades\Readers\LanguageReader;
use App\Model\Facades\Readers\NewsReader;
use App\Model\Facades\Readers\TemplateReader;
use App\Model\Services\NewsService;
use Throwable;

class NewsWriter extends BaseWriter
{
    /** @var  NewsService */
    protected $newsService;
    /** @var  NewsReader */
    protected $newsReader;
    /** @var  LanguageReader */
    protected $languageReader;
    /** @var  TemplateReader */
    protected $templateReader;

    public function inject(NewsService $newsService, NewsReader $newsReader, LanguageReader $languageReader, TemplateReader $templateReader)
    {
        $this->newsService = $newsService;
        $this->newsReader = $newsReader;
        $this->languageReader = $languageReader;
        $this->templateReader = $templateReader;
    }

    public function createNewsContainer($template, string $name) : NewsContainer
    {
        $templateEntity = $this->templateReader->validateNewsTemplate($template);

        try {
            $this->beginTransaction();
            $container = $this->newsService->createContainer($this->getLoggedInUser(), $templateEntity, $name);
            $container->setState(NewsContainer::ACTIVE);
            $this->commit();
        } catch (Throwable $e) {
            $this->rollback();
            throw $e;
        }

        return $container;
    }

    public function createNews($container, $language, string $title, string $description, string $content = null, bool $publish = false) : News
    {
        $containerEntity = $this->newsReader->validateContainer($container);
        $languageEntity = $this->languageReader->validateLanguage($language);

        try {
            $this->beginTransaction();
            $news = $this->newsService->createNews($this->getLoggedInUser(), $containerEntity, $languageEntity, $title, $description, $content);
            if ($publish) {
                $this->publishNews($news);
            }
            $this->commit();
        } catch (Throwable $e) {
            $this->rollback();
            throw $e;
        }

        return $news;
    }

    public function editNews($news, $language, string $title, string $description, string $content = null, bool $publish = false) : News
    {
        $newsEntity = $this->newsReader->validateNews($news);
        $languageEntity = $this->languageReader->validateLanguage($language);

        try {
            $this->beginTransaction();
            $newsEntity->setEditedBy($this->getLoggedInUser());
            $newsEntity->setLanguage($languageEntity);
            $newsEntity->setTitle($title);
            $newsEntity->setDescription($description);
            $newsEntity->setContent($content);
            if ($publish) {
                $this->publishNews($newsEntity);
            }
            $this->commit();
        } catch (Throwable $e) {
            $this->rollback();
            throw $e;
        }

        return $newsEntity;
    }

    public function publishNews($news) : News
    {
        $newsEntity = $this->newsReader->validateNews($news);
        try {
            $this->beginTransaction();
            $newsEntity->setState(News::PUBLISHED);
            $newsEntity->setEditedBy($this->getLoggedInUser());
            $newsEntity->setPublishedAt(new \DateTime());
            $this->commit();
        } catch (Throwable $e) {
            $this->rollback();
            throw $e;
        }

        return $newsEntity;
    }
}