<?php

/**
 * Questo file è parte di Pongho.
 *
 * @author    Daniele Termini
 * @copyright Web Agency Meta Line S.r.l.
 * @package   Application\Admin
 */

namespace Application\Admin\Utilities;

use Application\Admin\Controller\Crud2Controller;
use Application\Core\Utilities\ControllerHelper;
use Pongho\Core\TemplateResponse;
use Pongho\Template\CompositeView;
use Pongho\Template\View;

class AdminControllerHelper extends ControllerHelper
{
    /**
     * @var CompositeView
     */
    protected $compositeView;

    /**
     * @var View
     */
    protected $headerView;

    /**
     * @var View
     */
    protected $bodyView;

    /**
     * @var View
     */
    protected $footerView;

    /**
     * @var \Application\Core\Model\Site
     */
    protected $site;

    /**
     * @var string
     */
    protected $moduleSiteClass = \Application\Core\Model\ModuleSite::class;

    /**
     * {@inheritdoc}
     */
    public function displayMessage($message, $is_error = false, array $parameters = [])
    {
        /** @var \Pongho\Http\Request $request */
        $request = $this->container->get('request');

        if ($request->isAjax()) {
            return $this->displayJsonMessage($message, $is_error, $parameters);
        }

        /** @var \Application\Core\I18n\Translation\Translator $translator */
        $translator = $this->container->get('translator');

        $default = [
            'title' => $is_error ? $translator->trans('Attention') : $translator->trans('Message'),
        ];

        $parameters['message'] = $message;
        $parameters['error'] = $is_error;

        $parameters = array_merge($default, $parameters);

        $this->getBodyView()
            ->setTemplatePath(__DIR__ . '/../Resources/views/message.php')
            ->assignVars($parameters);

        return new TemplateResponse($this->getView(), $this->getResponseHeaders());
    }

    /**
     * @param string $link
     * @return $this
     */
    public function addJavascript($link, array $attributes = [])
    {
        /** @var \Pongho\Template\Helper\JavaScript $js */
        $js = $this->container->get('admin.footer_js');

        $js->add($link, $attributes);

        return $this;
    }

    /**
     * @param string $code
     * @return $this
     */
    public function addJavascriptInline($code, array $attributes = [])
    {
        /** @var \Pongho\Template\Helper\JavaScript $js */
        $js = $this->container->get('admin.footer_js');

        $js->addInline($code, $attributes);

        return $this;
    }

    /**
     * @param string $link
     * @return $this
     */
    public function addCss($link, array $attributes = [])
    {
        /** @var \Pongho\Template\Helper\Css $css */
        $css = $this->container->get('admin.css');

        $css->add($link, $attributes);

        return $this;
    }

    /**
     * Load Select2 (https://select2.github.io/)
     *
     * @return $this
     */
    public function loadSelect2()
    {
        $this
            ->addCss(pongho_url(
                '/Application/Admin/Resources/views/vendor/select2/css/select2.min.css?v='
                . filemtime(PONGHO_PATH . '/Application/Admin/Resources/views/vendor/select2/css/select2.min.css')
            ))
            ->addJavascript(pongho_url(
                '/Application/Admin/Resources/views/vendor/select2/js/select2.full.min.js?v='
                . filemtime(PONGHO_PATH . '/Application/Admin/Resources/views/vendor/select2/js/select2.full.min.js')
            ))
        ;

        return $this;
    }

    /**
     * Load the wysiwyg editor (TinyMCE - https://www.tiny.cloud/)
     *
     * @param null|Crud2Controller $controller
     * @param bool                 $init
     * @return $this
     */
    public function loadEditorWysiwyg(array $options = [], $controller = null, $init = false)
    {
        if ($controller !== null && !($controller instanceof Crud2Controller)) {
            throw new \InvalidArgumentException(sprintf(
                'The controller must be null or an instance of %s in %s',
                Crud2Controller::class,
                __METHOD__
            ));
        }

        $translator = $this->getTranslator();
        $language = $this->getUser()->getAccount()->getLanguage()->getCulture();

        if (!file_exists(__DIR__ . '/../Resources/vendor/tinymce/langs/' . $language . '.js')) {
            if (strlen($language) > 2) {
                $language = substr($language, 0, 2);

                if (!file_exists(__DIR__ . '/../Resources/vendor/tinymce/langs/' . $language . '.js')) {
                    $language = 'it';
                }
            } else {
                $language = 'it';
            }
        }

        $options = array_merge(
            [
                'language'                => $language,

                // Dimensioni
                'width'                   => '100%',

                // HTML5
                'element_format'          => 'html', // sostituisce '<br />' con '<br>'
                'fix_list_elements'       => true, // corregge le liste indentate male
                'schema'                  => 'html5-strict',
                'extended_valid_elements' => 'span[style|id|nam|class|lang]',

                // CSS
                'content_css'             => pongho_url(
                    '/Application/Admin/Resources/views/css/editor-content.css?v=' . filemtime(
                        __DIR__ . '/../Resources/views/css/editor-content.css'
                    )
                ),

                // Caratteri accentati
                'entity_encoding'         => 'raw',
                'convert_urls'            => false,
            ],
            $options
        );

        $options = $this->filter(null, 'admin.filter_wysiwyg_options', $options);

        if ($controller instanceof Crud2Controller) {
            $options = $this->filter($controller, $controller->getEventNamespace('filter_wysiwyg_options'), $options);
        }

        // Opzioni Normal
        $optionsNormal = array_merge(
            $options,
            [
                // Plugins
                'plugins'                   => 'advlist anchor charmap code contextmenu directionality fullscreen hr image link lists media paste print responsivefilemanager searchreplace tabfocus table textcolor visualblocks wordcount',

                // Menu
                'menu'                      => [
                    'edit'   => [
                        'title' => $translator->trans('Edit', [], 'wysiwyg'),
                        'items' => 'undo redo | searchreplace | selectall',
                    ],
                    'format' => [
                        'title' => $translator->trans('Format', [], 'wysiwyg'),
                        'items' => 'bold italic underline strikethrough | subscript superscript | formats | removeformat',
                    ],
                    'insert' => [
                        'title' => $translator->trans('Insert', [], 'wysiwyg'),
                        'items' => 'link anchor | hr | image media | charmap',
                    ],
                    'table'  => [
                        'title' => $translator->trans('Table', [], 'wysiwyg'),
                        'items' => 'inserttable tableprops deletetable cell row column',
                    ],
                    'tools'  => [
                        'title' => $translator->trans('Tools', [], 'wysiwyg'),
                        'items' => 'visualblocks fullscreen | print code | spellcheck',
                    ],
                ],

                // Strumenti
                'toolbar'                   => [
                    'formatselect | bold italic underline forecolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link unlink image media',
                ],

                // Tabelle
                'visual'                    => true,

                // Allineamento
                'formats'                   => [
                    'alignleft'    => [
                        'selector' => 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img',
                        'classes'  => 'alignleft',
                    ],
                    'alignright'   => [
                        'selector' => 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img',
                        'classes'  => 'alignright',
                    ],
                    'alignjustify' => [
                        'selector' => 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img',
                        'classes'  => 'alignfull',
                    ],
                    'aligncenter'  => [
                        'selector' => 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img',
                        'classes'  => 'aligncenter',
                    ],
                ],

                // Plugin
                'external_plugins'          => [
                    'filemanager' => pongho_url('/Application/Admin/Resources/vendor/responsivefilemanager/plugin.min.js'),
                    'nanospell'   => pongho_url('/Application/Admin/Resources/vendor/nanospell/plugin.js'),
                ],

                // FileManager - http://www.responsivefilemanager.com/
                'external_filemanager_path' => pongho_url('/Application/Admin/Resources/vendor/responsivefilemanager/'),
                'filemanager_title'         => $translator->trans('File manager', [], 'wysiwyg'),
                'site'                      => $this->getSite()->getId(),

                // Nanospell - http://tinymcespellcheck.com/
                'nanospell_server'          => 'php',

                /**
                 * Extends <iframe> support
                 *
                 * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe
                 * @see https://www.tiny.cloud/docs-3x/reference/configuration/Configuration3x@extended_valid_elements/
                 */
                'extended_valid_elements'   => ''
                    . 'iframe[align<bottom?left?middle?right?top|allow|allowfullscreen|allowpaymentrequest'
                    . '|class|frameborder|height|id|longdesc|marginheight|marginwidth|name|referrerpolicy'
                    . '|sandbox|scrolling<auto?no?yes|src|srcdoc|style|title|width]',
            ]
        );

        // Opzioni Small
        $optionsSmall = array_merge(
            $options,
            [
                // Plugins
                'plugins' => 'advlist code link lists wordcount',

                // Menu
                'menubar' => false,

                // Strumenti
                'toolbar' => [
                    'bold italic underline bullist numlist link unlink | code',
                ],
            ]
        );

        // Opzioni Full
        $optionsFull = array_merge(
            $optionsNormal,
            [
                'plugins' => 'advlist anchor charmap code contextmenu directionality fullpage fullscreen hr image link lists media paste print responsivefilemanager searchreplace tabfocus table textcolor visualblocks wordcount',

                // Strumenti
                'toolbar' => [
                    'formatselect | fontselect | fontsizeselect | forecolor backcolor | removeformat',
                    'bold italic underline | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link unlink | image media',
                ],
            ]
        );

        // Opzioni Newsletter
        $optionsNewsletter = array_merge(
            $optionsFull,
            [
                // Schema
                'schema'                       => 'html4',

                // Fullpage
                'fullpage_default_doctype'     => '',
                'fullpage_default_encoding'    => 'UTF-8',
                'fullpage_default_title'       => 'Newsletter',
                'fullpage_default_font_size'   => '12px',
                'fullpage_default_font_family' => "'Lucida Grande', Lucida, Verdana, sans-serif",
                'fullpage_default_text_color'  => '#333',
                'fullpage_default_xml_pi'      => false,
                'fullpage_hide_in_source_view' => false,
            ]
        );

        unset($optionsNewsletter['formats']);

        // Filtri
        $optionsNormal = $this->filter($this, 'admin.filter_wysiwyg_options.normal', $optionsNormal);
        $optionsSmall = $this->filter($this, 'admin.filter_wysiwyg_options.small', $optionsSmall);
        $optionsFull = $this->filter($this, 'admin.filter_wysiwyg_options.full', $optionsFull);
        $optionsNewsletter = $this->filter($this, 'admin.filter_wysiwyg_options.newsletter', $optionsNewsletter);

        if ($controller instanceof Crud2Controller) {
            $optionsNormal = $this->filter(
                $controller,
                $controller->getEventNamespace('filter_wysiwyg_options.normal'),
                $optionsNormal
            );

            $optionsSmall = $this->filter(
                $controller,
                $controller->getEventNamespace('filter_wysiwyg_options.small'),
                $optionsSmall
            );

            $optionsFull = $this->filter(
                $controller,
                $controller->getEventNamespace('filter_wysiwyg_options.full'),
                $optionsFull
            );
        }

        // Javascript
        $options = json_encode([
            'normal'     => $optionsNormal,
            'small'      => $optionsSmall,
            'full'       => $optionsFull,
            'newsletter' => $optionsNewsletter,
        ]);

        $siteDomain = $this->getSite()->getDomain();

        $jsInline = <<<JS
    Pongho.wysiwyg = {
        options: $options
    };

    /**
     * Pongho.wysiwyg.cleanUrls()
     *
     * Serve a mantenere inalterati gli shortcode inseriti negli attributi href e src dei tag
     * ATTENZIONE: gli url relativi devono essere inseriti con / iniziale altrimenti non vengono convertiti
     *
     * Dati i link
     * <p><a href="[config key='company_website' /]">url con shortcode [</a></p>
     * <p><a href="{COMPANY_WEBSITE}">url con shortcode { (non viene parsato dai nodi)</a></p>
     * <p><a href="/prova-url-shortcode/">url relativo</a></p>
     * <p><a href="http://www.google.it">url assoluto</a></p>
     *
     * L'output risulta in
     * <p><a href="[config key='company_website' /]">url con shortcode [</a></p>
     * <p><a href="{COMPANY_WEBSITE}">url con shortcode { (non viene parsato dai nodi)</a></p>
     * <p><a href="http://www.domain.it/prova-url-shortcode/">url relativo</a></p>
     * <p><a href="http://www.google.it">url assoluto</a></p>
     */
    Pongho.wysiwyg.cleanUrls = function (editor) {
        // http://www.tinymce.com/wiki.php/api4:method.tinymce.Editor.convertURL
        editor.originalConvertUrl = editor.convertURL;

        editor.convertURL = function (url, name, elm) {
            if (typeof url === 'string') {
                if (url[0] === '/' && url[1] != '/') {
                    url = '{$siteDomain}' + url;
                }
            }

            return editor.originalConvertUrl(url, name, elm);
        };
    };

    /**
     * Pongho.wysiwyg.fixInitialContent()
     */
    Pongho.wysiwyg.fixInitialContent = function (editor) {
        editor.on('init', function() {
            var doc = $(editor.dom.doc);

            doc.find('table').each(function () {
                var table = $(this);

                if (table.attr('width')) {
                    table.css('width', table.attr('width'));
                }

                if (table.attr('bgcolor')) {
                    table.css('background-color', table.attr('bgcolor'));
                }

                if (table.attr('align') === 'center') {
                    table.css({
                        marginLeft: 'auto',
                        marginRight: 'auto'
                    });
                }
            });

            doc.find('td, th').each(function () {
                var td = $(this);

                if (td.attr('width')) {
                    td.css('width', td.attr('width'));
                }

                if (td.attr('bgcolor')) {
                    td.css('background-color', td.attr('bgcolor'));
                }

                if (td.attr('align')) {
                    td.css('text-align', td.attr('align'));

                    td.children('table').css({
                        marginLeft: 'auto',
                        marginRight: 'auto'
                    });
                }
            });
        });
    };

    /**
     * Pongho.wysiwyg.setup()
     */
    Pongho.wysiwyg.setup = function (editor) {
        Pongho.wysiwyg.cleanUrls(editor);
        Pongho.wysiwyg.fixInitialContent(editor);
    };

    Pongho.wysiwyg.options.normal.setup = Pongho.wysiwyg.setup;
    Pongho.wysiwyg.options.small.setup = Pongho.wysiwyg.setup;
    Pongho.wysiwyg.options.full.setup = Pongho.wysiwyg.setup;
    Pongho.wysiwyg.options.newsletter.setup = Pongho.wysiwyg.setup;

    var types = [
        {
            selector: 'textarea.tinymce',
            options: 'normal'
        },
        {
            selector: 'textarea.tinymce-small',
            options: 'small'
        },
        {
            selector: 'textarea.tinymce-full',
            options: 'full'
        },
        {
            selector: 'textarea.tinymce-newsletter',
            options: 'newsletter'
        }
    ];

    function removeTinyMCE(elementId) {
        if (tinymce.get(elementId)) {
            tinymce.EditorManager.execCommand('mceRemoveEditor', false, elementId);
        }
    }

    function loop(container, callback) {
        container = $(container);

        if (!container.length) {
            return;
        }

        types.forEach(function (type) {
            container.find(type.selector).each(function () {
                var textarea = $(this);
                var id = textarea.attr('id');

                callback(id, textarea, type.options);
            });
        });
    }

    Pongho.wysiwyg.attach = function(container) {
        loop(container, function (id, textarea, optionsType) {
            removeTinyMCE(id);

            var opts = $.extend({}, Pongho.wysiwyg.options[optionsType], textarea.data());

            textarea
                .css('height', function () {
                    return $(this).attr('rows') + 'em';
                })
                .tinymce(opts);
        });
    };

    Pongho.wysiwyg.detach = function(container) {
        loop(container, removeTinyMCE);
    };
JS;

        if ($init) {
            $jsInline .= "\n\n\tPongho.wysiwyg.attach(document.body);";
        }

        $this
            ->addJavascript(pongho_url(
                '/Application/Admin/Resources/vendor/tinymce/tinymce.min.js?v='
                . filemtime(PONGHO_PATH . '/Application/Admin/Resources/vendor/tinymce/tinymce.min.js')
            ))
            ->addJavascript(pongho_url(
                '/Application/Admin/Resources/vendor/tinymce/jquery.tinymce.min.js?v='
                . filemtime(PONGHO_PATH . '/Application/Admin/Resources/vendor/tinymce/jquery.tinymce.min.js')
            ))
            ->addJavascriptInline(
                $jsInline
            );

        return $this;
    }

    /**
     * {@inheritdoc}
     *
     * @deprecated Utilizza i metodi addJavascript(), addJavascriptInline() e addCss()
     */
    public function getHead()
    {
        return $this->container->get('admin.template_head');
    }

    /**
     * {@inheritdoc}
     *
     * @return CompositeView
     */
    public function getView()
    {
        if (null === $this->compositeView) {
            $this->compositeView = new CompositeView();
            $this->compositeView
                ->attachView($this->getHeaderView())
                ->attachView($this->getBodyView())
                ->attachView($this->getFooterView());
        }

        return $this->compositeView;
    }

    /**
     * @return \Pongho\Template\View
     */
    public function getHeaderView()
    {
        if (null === $this->headerView) {
            $this->headerView = new View(__DIR__ . '/../Resources/views/header.php');
            $this->headerView->assignVars($this->getViewGlobalVariables());
        }

        return $this->headerView;
    }

    /**
     * @return \Pongho\Template\View
     */
    public function getBodyView()
    {
        if (null === $this->bodyView) {
            $this->bodyView = new View(__DIR__ . '/../Resources/views/default.php');
            $this->bodyView->assignVars($this->getViewGlobalVariables());
        }

        return $this->bodyView;
    }

    /**
     * @return \Pongho\Template\View
     */
    public function getFooterView()
    {
        if (null === $this->footerView) {
            $this->footerView = new View(__DIR__ . '/../Resources/views/footer.php');
            $this->footerView->assignVars($this->getViewGlobalVariables());
            $this->footerView->assignVar('sidebar_menu', $this->container->get('admin_sidebar'));
        }

        return $this->footerView;
    }

    /**
     * Restituiesce le variabili globali per la vista
     */
    public function getViewGlobalVariables()
    {
        return [
            'head'       => $this->getHead(),
            'html'       => $this->container->get('template_html'),
            'translator' => $this->container->get('translator'),
            'lang'       => $this->container->get('language'),
            'language'   => $this->getLanguage(),
            'site'       => $this->getSite(),
            'user'       => $this->getUser(),
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function getSite()
    {
        if (null === $this->site) {
            /** @var \Pongho\Http\Request $request */
            $request = $this->container->get('request');

            if ($request->query->has('site') || $this->container->hasParameter('site_id')) {
                $this->site = $this->container->get('site');
            } else {
                $this->site = $this->container->get('main_site');
            }
        }

        return $this->site;
    }

    /**
     * @return int
     */
    public function getModuleId()
    {
        return $this->container->getParameter('module_id');
    }

    /**
     * Imposta una classe per il ModuleSite
     *
     * @param string $moduleSiteClass
     */
    public function setModuleSiteClass($moduleSiteClass)
    {
        $this->moduleSiteClass = $moduleSiteClass;
    }

    /**
     * @return string|\Application\Core\Model\ModuleSite
     */
    public function getModuleSiteClass()
    {
        return $this->moduleSiteClass;
    }

    /**
     * Restituisce il modello ModuleSite corrente.
     *
     * @param boolean $throwException
     * @return \Application\Core\Model\ModuleSite
     * @throws \UnexpectedValueException Quando il modulo amministrativo non è associato ad alcun modulo.
     */
    public function getModuleSite($throwException = true)
    {
        if (null === $this->moduleSite) {
            $module_id = $this->getModuleId();

            if ($module_id === null) {
                if ($throwException) {
                    throw new \UnexpectedValueException('L\'item corrente del menu ha un "module_id" non valido.');
                }

                return null;
            } else {
                $site = $this->getSite();
                $language = $this->getLanguage();
                $class = $this->getModuleSiteClass();

                $this->moduleSite = $class::findById($module_id, $site->id, $language->language_id);
            }
        }

        return $this->moduleSite;
    }

    /**
     * Restituisce la lingua per l'interfaccia
     *
     * @return int
     */
    public function getContentLanguageId()
    {
        /** @var \Application\Admin\Utilities\ContentLanguage $contentLanguage */
        $contentLanguage = $this->container->get('content_language');

        return $contentLanguage->getId();
    }
}
