<?php
// Copyright (c) Pickware GmbH. All rights reserved.
// This file is part of software that is released under a proprietary license.
// You must not copy, modify, distribute, make publicly available, or execute
// its contents or parts thereof without express permission by the copyright
// holder, unless otherwise permitted by law.

namespace Shopware\Plugins\ViisonCommon\Components\SubApplicationLoading\SubApplicationCodeGenerator;

use Shopware\Components\DependencyInjection\Container;
use Shopware\Plugins\ViisonCommon\Components\ControllerFactoryService;

class PlainSubApplicationCodeGenerator extends AbstractSubApplicationCodeGenerator
{
    /**
     * @var \Zend_Db_Adapter_Abstract
     */
    protected $db;

    /**
     * @var \Shopware_Components_Snippet_Manager
     */
    private $snippetManager;

    /**
     * @param Container $dependencyContainer
     * @param \Enlight_Controller_Front $frontController
     * @param \Enlight_Loader $classLoader
     * @param \Enlight_Event_EventManager $eventEventManager
     * @param ControllerFactoryService $controllerFactoryService
     * @param \Zend_Db_Adapter_Abstract $db
     * @param \Shopware_Components_Snippet_Manager $snippetManager
     * @param string $name
     * @param string $path
     * @param string $controllerClass
     */
    public function __construct(
        Container $dependencyContainer,
        \Enlight_Controller_Front $frontController,
        \Enlight_Loader $classLoader,
        \Enlight_Event_EventManager $eventEventManager,
        ControllerFactoryService $controllerFactoryService,
        \Zend_Db_Adapter_Abstract $db,
        \Shopware_Components_Snippet_Manager $snippetManager,
        $name,
        $path,
        $controllerClass
    ) {
        parent::__construct(
            $dependencyContainer,
            $frontController,
            $classLoader,
            $eventEventManager,
            $controllerFactoryService,
            $name,
            $path,
            $controllerClass
        );
        $this->db = $db;
        $this->snippetManager = $snippetManager;
    }

    /**
     * @inheritdoc
     */
    public function generateSubApplicationCode()
    {
        // Prepend any view parameters and snippets as JavaScript calls
        $renderedApp = $this->renderViewParametersAsJavaScript() . "\n";
        $renderedApp .= $this->renderSnippetsAsJavaScript() . "\n";

        // Concatenate the content of all app files
        $files = $this->getSubAppFiles();
        $fileContents = array_map('file_get_contents', array_unique($files));
        $renderedApp .= implode("\n", $fileContents) . "\n";

        return $renderedApp;
    }

    /**
     * @return string
     */
    private function renderViewParametersAsJavaScript()
    {
        $viewParams = $this->getViewParameters();
        if (!is_array($viewParams) || count($viewParams) === 0) {
            return '';
        }

        return 'ViisonCommonApp.addConfig(\'' . $this->name . '\', ' . json_encode($viewParams) . ');';
    }

    /**
     * @return string
     */
    private function renderSnippetsAsJavaScript()
    {
        // Find all namespaces that contain the sub app name
        $subAppNamespaceIdentifier = self::convertPascalCaseToSnakeCase($this->name);
        $subAppNamespaces = $this->db->fetchCol(
            'SELECT DISTINCT namespace
            FROM s_core_snippets
            WHERE namespace = :exactMatch
                OR namespace LIKE :prefixMatch
                OR namespace LIKE :infixMatch
                OR namespace LIKE :suffixMatch',
            [
                'exactMatch' => $subAppNamespaceIdentifier,
                'prefixMatch' => $subAppNamespaceIdentifier . '/%',
                'infixMatch' => '%/' . $subAppNamespaceIdentifier . '/%',
                'suffixMatch' => '%/' . $subAppNamespaceIdentifier,
            ]
        );

        // Try to get any extra namespaces
        $controller = $this->loadBackendController();
        if ($controller && method_exists($controller, 'getExtraSnippetNamespaces')) {
            $subAppNamespaces = array_merge($subAppNamespaces, $controller->getExtraSnippetNamespaces());
        }

        // Load all snippets of all namespaces
        $snippets = [];
        foreach ($subAppNamespaces as $namespace) {
            $snippets[$namespace] = $this->snippetManager->getNamespace($namespace)->toArray();
        }
        if (count($snippets) === 0) {
            return '';
        }

        return 'ViisonCommonApp.addSnippetNamespaces(' . json_encode($snippets) . ');';
    }
}
