<?php

namespace Comitium5\DesignerBundle\Manager\Page;

use Comitium5\ApiClientBundle\ApiClient\ResourcesTypes;
use Comitium5\ApiClientBundle\Client\Client;
use Comitium5\ApiClientBundle\Client\Services\ActivitiesApiService;
use Comitium5\ApiClientBundle\Client\Services\ArticleApiService;
use Comitium5\ApiClientBundle\Client\Services\AuthorApiService;
use Comitium5\ApiClientBundle\Client\Services\ClassifiedApiService;
use Comitium5\ApiClientBundle\Client\Services\ContestApiService;
use Comitium5\ApiClientBundle\Client\Services\DirectoryItemApiService;
use Comitium5\ApiClientBundle\Client\Services\GalleryApiService;
use Comitium5\ApiClientBundle\Client\Services\LiveEventApiService;
use Comitium5\ApiClientBundle\Client\Services\PollApiService;
use Comitium5\ApiClientBundle\Utils\ResponseUtils;
use Comitium5\ApiClientBundle\ValueObject\IdentifiedValue;
use Comitium5\DesignerBundle\Entity\Page;
use Comitium5\DesignerBundle\Factory\AbstractFactory;
use Comitium5\DesignerBundle\Helper\Utils;
use Comitium5\DesignerBundle\Manager\AbstractManager;
use Comitium5\DesignerBundle\Manager\Designer\DesignerManager;
use Comitium5\DesignerBundle\Manager\View\ViewManager;
use Comitium5\DesignerBundle\Model\Interfaces\LocaleInterface;
use Comitium5\DesignerBundle\Model\Interfaces\Page\PageInterface;
use Comitium5\DesignerBundle\Model\Interfaces\SerializeInterface;
use Comitium5\DesignerBundle\Model\Interfaces\View\ViewInterface;
use Comitium5\DesignerBundle\Model\PageType;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\Persistence\ObjectRepository;

/**
 * Class PageManager
 *
 * @author Carles Gómez <carles@bab-soft.com>
 * @package Comitium5\DesignerBundle\Manager\Page
 */
class PageManager extends AbstractManager
{
    const TWIG_PATH = 'Resources/views/Designer/%s';
    const FOLDER_PERMISSION = 0755;


    /**
     * @var ViewManager
     */
    private $viewManager;

    /**
     * @var Client
     */
    private $apiClient;

    /**
     * PageManager constructor.
     *
     * @param AbstractFactory $factory
     * @param ObjectRepository $repository
     * @param ObjectManager $objectManager
//     * @param WorkflowManager $workflowManager
     * @param ViewManager $viewManager
     * @param Client $apiClient
     */
    public function __construct(
        AbstractFactory $factory,
        ObjectRepository $repository,
        ObjectManager $objectManager,
        ViewManager $viewManager,
        Client $apiClient
    ) {
        $this->factory = $factory;
        $this->repository = $repository;
        $this->objectManager = $objectManager;
        $this->viewManager = $viewManager;
        $this->apiClient = $apiClient;
    }

    /**
     * @param $item
     *
     * @return mixed
     */
    public function cloneItem($item)
    {
        $clonedItem = clone $item;

        $this->cloneHandler($clonedItem, $item);

        $clonedItem->setCreatedAt(new \DateTime('NOW'));
        $clonedItem->setUpdatedAt(new \DateTime('NOW'));

        foreach ($item->getLangs() as $lang) {
            $clonedItem->addLang($this->cloneItemLang($lang));
        }

        return $clonedItem;
    }

    private function cloneItemLang(PageLangInterface $entity)
    {
        $clonedItem = clone $entity;
        $clonedItem->setName($this->translator->trans('cs_core.label.copy_of').$clonedItem->getName());

        $this->cloneHandler($clonedItem);

        return $clonedItem;
    }

    /**
     * @param PageInterface $page
     * @param $code
     * @param bool          $temporary
     *
     * @return bool
     */
    public function saveFile(PageInterface $page, $code, $temporary = false)
    {
        try {
            $this
                ->viewManager
                ->create(
                    sprintf(
                        DesignerManager::BUNDLE_TWIG_PATH,
                        $page->getFilePath($temporary)
                    ),
                    $code,
                    $page
                );
        } catch (\Exception $exception) {
            return false;
        }

        return true;
    }

    /**
     * @param $path
     *
     * @return string
     * @throws \Exception
     */
    public function getCode($path)
    {
        $filePath = sprintf(DesignerManager::BUNDLE_TWIG_PATH, $path);

        $view = $this
            ->viewManager
            ->findByName($filePath);

        if ($view instanceof ViewInterface) {
            return $view->getContent();
        }

        throw new \Exception("No view found with name ".$filePath);
    }

    /**
     * Publish page. Set publish date, update workflow state, purge varnish url
     *
     * @param PageInterface $page
     *
     * @return mixed
     */
    public function publish(PageInterface $page, LocaleInterface $locale = null)
    {
        $page->setPublishedAt(new \DateTime('NOW'));
        $page->setUnPublishedAt(null);

        return $this->update($page);
    }

    /**
     * unPublish page. Set unPublish date, purge varnish url
     *
     * @param PageInterface $page
     *
     * @return mixed
     */
    public function unPublish(PageInterface $page)
    {
        $page->setPublishedAt(null);
        $page->setUnPublishedAt(new \DateTime('NOW'));

        return $this->update($page);
    }

    /**
     * @param PageInterface $page
     *
     * @return string
     */
    public function buildFilePath(PageInterface $page)
    {
        return sprintf(
            DesignerManager::BUNDLE_TWIG_PATH,
            $page->getFilePath()
        );
    }

    /**
     * @param PageInterface $page
     *
     * @return bool
     */
    public function existFilePath(PageInterface $page)
    {
        $view = $this
            ->viewManager
            ->findByName($this->buildFilePath($page));

        return $view instanceof ViewInterface;
    }

    /**
     * @param $contentId
     * @param $contentType
     *
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function fetchEntityByPageType(
        $contentId,
        $contentType
    ): array {
        $response = $this
            ->apiClient
            ->find($contentType, $contentId);

        return ResponseUtils::isValidResponse($response) ?
            $response["data"] :
            [];
    }
}
