<?php

namespace Comitium5\DesignerBundle\Manager\Widget;

use Comitium5\DesignerBundle\Controller\Widget\AbstractDesignerWidgetController;
use Comitium5\DesignerBundle\Model\Interfaces\Layout\LayoutInterface;
use Comitium5\DesignerBundle\Model\Interfaces\Layout\LayoutPageWidgetInterface;
use Comitium5\DesignerBundle\Model\Interfaces\Page\PageInterface;
use Comitium5\DesignerBundle\Model\Interfaces\Template\TemplateInterface;
use Comitium5\DesignerBundle\Provider\SubsiteProvider;
use Comitium5\DesignerBundle\Publisher\Page\PageContentResolver;
use Symfony\Component\HttpFoundation\Response;

/**
 * Class WidgetVisualEditorManager
 *
 * @author Carles Gómez <carles@bab-soft.com>
 * @package Comitium5\DesignerBundle\Manager\Widget
 */
class WidgetVisualEditorManager
{
    /**
     * @var PageContentResolver
     */
    private $pageContentResolver;

    /**
     * @var SubsiteProvider
     */
    private $subSiteProvider;

    /**
     * @var array
     */
    private $locales;

    /**
     * WidgetVisualEditorManager constructor.
     *
     * @param PageContentResolver $pageContentResolver
     * @param SubsiteProvider $subSiteProvider
     *
     * @throws \Exception
     */
    public function __construct(
        PageContentResolver $pageContentResolver,
        SubSiteProvider $subSiteProvider
    )
    {
        $this->pageContentResolver = $pageContentResolver;
        $this->subSiteProvider = $subSiteProvider;
        $this->locales = $this->buildLocales();
    }

    /**
     * @param TemplateInterface $template
     * @param string|null $localeCode
     * @return array
     */
    public function generateVisualEditorDataFromTemplate(
        TemplateInterface $template,
        $localeCode = null
    )
    {
        $data = [];
        $layouts = $template->getLayouts();

        foreach($layouts as $layout) {
            $data += $this->generateVisualEditorDataFromLayout($layout, null, $localeCode);
        }

        return $data;
    }

    /**
     * @param LayoutInterface $layout
     * @param PageInterface|null $page
     * @param string|null $localeCode
     *
     * @return array $data
     */
    public function generateVisualEditorDataFromLayout(LayoutInterface $layout, PageInterface $page = null, $localeCode = null)
    {
        $data = [];

        $layoutPages = $layout->getLayoutPages();
        foreach($layoutPages as $layoutPage) {
            $layoutPagePage = $layoutPage->getPage();

            if($layoutPagePage === null || $layoutPagePage === $page) {
                $layoutPageWidgets = $layoutPage->getLayoutPageWidgets();

                foreach($layoutPageWidgets as $layoutPageWidget) {
                    $data[$layoutPageWidget->getId()] = $this->generateVisualEditorDataFromLayoutPageWidget($layoutPageWidget, $localeCode);
                }
            }
        }

        $children = $layout->getChildren();
        foreach($children as $child) {
            $data += $this->generateVisualEditorDataFromLayout($child, $page, $localeCode);
        }

        return $data;
    }

    /**
     * @param PageInterface $page
     * @param null $localeCode
     *
     * @return array
     * @throws \Exception
     */
    public function generateVisualEditorDataFromPage(
        PageInterface $page,
        $localeCode = null
    )
    {
        $designerManager = $this->pageContentResolver->getDesignerManager();
        $designerManager->setForceTmp(true);
        $htmlContent = $designerManager->generateHtmlPage($page);

        $layoutsPageWidgets = $this->pageContentResolver->resolveLayoutPageWidgets($htmlContent);

        $data = [];

        foreach ($layoutsPageWidgets as $layoutsPageWidget) {
            if ($layoutsPageWidget instanceof LayoutPageWidgetInterface) {
                $data[$layoutsPageWidget->getId()] = $this->generateVisualEditorDataFromLayoutPageWidget($layoutsPageWidget, $localeCode);
            }
        }

        return $data;
    }

    /**
     * @param LayoutPageWidgetInterface $layoutPageWidget
     * @param null $localeCode
     * @return array
     */
    public function generateVisualEditorDataFromLayoutPageWidget(
        LayoutPageWidgetInterface $layoutPageWidget,
        $localeCode = null
    )
    {
        $widget = $layoutPageWidget->getWidget();
        $controller = $this->pageContentResolver->getWidgetBuilder()->buildWidgetController($widget);
        $parameters = $this->resolveWidgetParametersToController($layoutPageWidget);

        return $this->generateEditorData($controller, $parameters, $localeCode);
    }

    /**
     * @param LayoutPageWidgetInterface $layoutPageWidget
     * @return array
     */
    public function resolveWidgetParametersToController(LayoutPageWidgetInterface $layoutPageWidget)
    {
        $parameters = $layoutPageWidget->getParameters();

        if (isset($parameters["fields"])) {
            $parameters["parameters"]["_fields"] = $parameters["fields"];
            unset($parameters["fields"]);
        }

        return $parameters;
    }

    /**
     * @param AbstractDesignerWidgetController $controller
     * @param array $parameters
     * @param null $localeCode
     *
     * @return array
     * @throws \Exception
     */
    public function generateEditorData(
        AbstractDesignerWidgetController $controller,
        array $parameters,
        $localeCode = null
    )
    {
        if ($localeCode !== null) {
            $this->locales = $this->buildLocales($localeCode);
        }

        $uuid = !empty($parameters["_uuid"]) ? $parameters["_uuid"] : null;
        $parameters = !empty($parameters["parameters"]) ? $parameters["parameters"] : [];

        // Force params to execute widget on visual editor mode
        $parameters['_editor'] = true;

        $data = [
            'parameters' => $parameters,
            'uuid'  => $uuid,
            'icons' => $controller->getIconPaths(),
            'css'   => $controller->getCssResourcesPaths(),
            'js'    => $controller->getJSResourcesPaths(),
            'html'  => [],
        ];

        foreach ($this->locales as $locale) {

            $parameters['_locale'] = $locale;

            try {
                $response = $controller->renderAction($parameters);

                if (!$response instanceof Response) {
                    continue;
                }

                $controller->resetDefaultValues();

                $data['html'][$locale] = $response->getContent();
            } catch (\Exception $e) {
                $controller->resetDefaultValues();
                continue;
            }
        }

        //Remover _editor parameter to avoid persist on DB by the visual editor
        if (isset($data["parameters"]["_editor"])) {
            unset($data["parameters"]["_editor"]);
        }

        // Set locales parameter for Subsite data
        if (isset($data["parameters"]["_locales"])) {
            $data["parameters"]["_locales"] = $this->locales;
        }

        return $data;
    }

    /**
     * @param null $localeCode
     *
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    private function buildLocales($localeCode = null)
    {
        $locales = [];

        foreach ($this->subSiteProvider->getSubsiteLocales() as $locale) {
            if ($localeCode !== null) {

                if ($locale->getCode() !== $localeCode) {
                    continue;
                }
            }

            $locales[] = $locale->getCode();
        }

        return $locales;
    }

    /**
     * @return array
     */
    public function getLocales()
    {
        return $this->locales;
    }

    /**
     * @param array $locales
     * @return $this
     */
    public function setLocales($locales)
    {
        $this->locales = $locales;

        return $this;
    }
}
