<?php

namespace Croogo\Core\View\Helper;

use BootstrapUI\View\Helper\HtmlHelper as BaseHtmlHelper;
use Cake\Event\Event;
use Cake\Utility\Hash;
use Cake\View\View;
use Croogo\Core\Status;
use Croogo\Extensions\CroogoTheme;

/**
 * Croogo Html Helper
 *
 * @package Croogo.Croogo.View.Helper
 */
class HtmlHelper extends BaseHtmlHelper
{

    public $helpers = [
        'Url',
        'Croogo/Core.Theme',
    ];

    /**
     * Constructor
     */
    public function __construct(View $View, $settings = [])
    {
        if ($View->getTheme()) {
            $themeConfig = CroogoTheme::config($View->getTheme());
            $themeSettings = $themeConfig['settings'];
            $settings = Hash::merge($themeSettings, $settings);
        }
        $boxContainerClass = 'card';
        $boxHeaderClass = 'card-header';
        $boxBodyClass = 'card-body';
        if (isset($settings['css'])) {
            $boxContainerClass = $settings['css']['boxContainerClass'];
            $boxHeaderClass = $settings['css']['boxHeaderClass'];
            $boxBodyClass = $settings['css']['boxBodyClass'];
        }
        $this->_defaultConfig['templates']['beginbox'] = "<div class='$boxContainerClass'>
                        <div class='$boxHeaderClass'>
                            {{icon}} {{title}}
                        </div>
                        <div class='$boxBodyClass'>";
        $this->_defaultConfig['templates']['endbox'] = '</div>
            </div>';

        parent::__construct($View, $settings);

        if (!$View->getTheme()) {
            return;
        }
    }

    /**
     * @return array
     */
    public function implementedEvents()
    {
        $events = parent::implementedEvents();
        $events['Helper.Layout.beforeFilter'] = [
            'callable' => 'filter',
            'passParams' => true,
        ];

        return $events;
    }

    /**
     * Filter content for Scripts and css tags
     *
     * Replaces [script:url] or [css:url] with script/css tags
     *
     * @param Event $event
     * @return string
     */
    public function filter(Event $event)
    {
        preg_match_all('/\[(script|css):([^] ]*)(.*?)\]/i', $event->getData('content'), $tagMatches);
        for ($i = 0, $ii = count($tagMatches[1]); $i < $ii; $i++) {
            $regex = '/(\S+)=[\'"]?((?:.(?![\'"]?\s+(?:\S+)=|[>\'"]))+.)[\'"]?/i';
            preg_match_all($regex, $tagMatches[3][$i], $attributes);
            $options = [];
            for ($j = 0, $jj = count($attributes[0]); $j < $jj; $j++) {
                $options[$attributes[1][$j]] = $attributes[2][$j];
            }
            $options = Hash::expand($options) + ['block' => true];

            if ($tagMatches[1][$i] === 'script') {
                $this->script($tagMatches[2][$i], $options);
            } elseif ($tagMatches[1][$i] === 'css') {
                $this->css($tagMatches[2][$i], $options);
            }

            $event->data['content'] = str_replace($tagMatches[0][$i], '', $event->data['content']);
        }

        return $event->getData();
    }

    /**
     * Creates a formatted IMG element.
     *
     * @see HtmlHelper::image()
     * @param string $path Image Path
     * @param array $options Options list
     * @return string Completed img tag
     */
    public function image($path, array $options = [])
    {
        $class = $this->Theme->getCssClass('imageClass');
        if (empty($options['class'])) {
            $options['class'] = $class;
        }

        return parent::image($path, $options);
    }

    /**
     * Creates a formatted IMG element for preview images.
     *
     * @see HtmlHelper::image()
     * @param string $path Image Path
     * @param array $options Options list
     * @return string Completed img tag
     */
    public function thumbnail($path, $options = [])
    {
        $class = $this->Theme->getCssClass('thumbnailClass');
        if (empty($options['class'])) {
            $options['class'] = $class;
        }

        return parent::image($path, $options);
    }

    /**
     * Create a string representing the start of a box container
     *
     * @param string $title Box title
     * @param options $options Option array
     * @returns string Start of box markup
     */
    public function beginBox($title = '', array $options = [])
    {
        $options = Hash::merge([
            'icon' => 'list',
        ], $options);

        $icon = $this->icon($options['icon']);
        unset($options['icon']);

        return $this->formatTemplate('beginbox', [
            'attrs' => $this->templater()
                ->formatAttributes($options),
            'icon' => $icon,
            'title' => $title,
        ]);
    }

    /**
     * Create a string that ends a box container
     *
     * @return string Box end markup
     */
    public function endBox()
    {
        return $this->formatTemplate('endbox', []);
        ;
    }

    /**
     * Returns a icon markup
     *
     * @param string $name Icon name/identifier without the prefix
     * @param array $options Icon html attributes
     * @return string Icon markup
     */
    public function icon($name, array $options = [])
    {
        $iconDefaults = $this->getConfig('iconDefaults');

        $defaults = [
            'iconSet' => $iconDefaults['iconSet'],
        ];
        $options += $defaults;

        return parent::icon($this->Theme->getIcon($name), $options);
    }

    /**
     * Create a link with icons with XHR toggleable status values
     *
     * @param string $value Current value
     * @param array $url Url in array format
     */
    public function status($value, $url = [])
    {
        $icon = $value == Status::PUBLISHED ? $this->Theme->getIcon('check-mark') : $this->Theme->getIcon('x-mark');
        $class = $value == Status::PUBLISHED ? 'green' : 'red';
        $iconTag = $this->icon($icon, ['class' => $class]);

        if (empty($url)) {
            return $iconTag;
        } else {
            return $this->link($iconTag, 'javascript:void(0);', [
                'escape' => false,
                'data-url' => $this->Url->build($url),
                'class' => "$class ajax-toggle",
            ]);
        }
    }

    /**
     * Add possibilities to parent::link() method
     *
     * ### Options
     *
     * - `escape` Set to true to enable escaping of title and attributes.
     * - `button` 'primary', 'info', 'success', 'warning', 'danger', 'inverse', 'link'.
     * http://twitter.github.com/bootstrap/base-css.html#buttons
     * - `icon` 'ok', 'remove' ... http://fortawesome.github.com/Font-Awesome/
     *
     * @param string $title The content to be wrapped by <a> tags.
     * @param string|array $url Cake-relative URL or array of URL parameters, or external URL (starts with http://)
     * @param array $options Array of HTML attributes.
     * @return string An `<a />` element.
     */
    public function link($title, $url = null, array $options = [])
    {
        $defaults = ['escape' => true];
        $options = is_null($options) ? [] : $options;
        $options = array_merge($defaults, $options);
        $iconDefaults = $this->getConfig('iconDefaults');

        if (!empty($options['button'])) {
            if (!empty($options['class'])) {
                $class = $options['class'];
            }
            $buttons = ['btn'];
            foreach ((array)$options['button'] as $button) {
                $buttons[] = 'btn-' . $button;
            }
            $options['class'] = trim(join(' ', $buttons));
            $options['class'] .= isset($class) ? ' ' . $class : null;
            unset($options['button']);
        }

        if (isset($options['icon'])) {
            $iconSize = $iconDefaults['size'];
            if (isset($options['iconSize']) && $options['iconSize'] === 'small') {
                $iconSize = $iconDefaults['size'];
                unset($options['iconSize']);
            }
            if (empty($options['iconInline'])) {
                $title = $this->icon($options['icon'], ['class' => $iconSize]) . $title;
            } else {
                $icon = trim($iconSize . ' ' . $iconDefaults['prefix'] . $this->Theme->getIcon($options['icon']));
                if (isset($options['class'])) {
                    $options['class'] .= ' ' . $icon;
                } else {
                    $options['class'] = ' ' . $icon;
                }
                unset($options['iconInline']);
            }
            $options['escapeTitle'] = false;
            unset($options['icon']);
        }

        if (isset($options['tooltip'])) {
            $tooltipOptions = [
                'rel' => 'tooltip',
                'data-placement' => 'top',
                'data-trigger' => 'hover',
            ];
            if (is_string($options['tooltip'])) {
                $tooltipOptions = array_merge([
                    'data-title' => $options['tooltip'],
                ], $tooltipOptions);
                $options = array_merge($options, $tooltipOptions);
            } else {
                $options['tooltip'] = array_merge($tooltipOptions, $options['tooltip']);
                $options = array_merge($options, $options['tooltip']);
            }
            unset($options['tooltip']);
        }

        return parent::link($title, $url, $options);
    }

    /**
     * Starts a new tab pane
     *
     * @param string $id Tab pane id
     * @param array $options Options array
     * @return string
     */
    public function tabStart($id, $options = [])
    {
        $options = Hash::merge([
            'id' => $id,
            'class' => 'tab-pane fade',
        ], $options);

        return $this->formatTemplate('blockstart', [
            'attrs' => $this->templater()
                ->formatAttributes($options),
        ]);
    }

    /**
     * Ends a tab pane
     *
     * @return string
     */
    public function tabEnd()
    {
        return $this->formatTemplate('blockend', []);
    }
}
