<?php

namespace onespace\tools\widgets\ui;

use Exception;
use onespace\tools\widgets\loaders\BounceLoader;
use Yii;
use yii\base\Widget;
use yii\helpers\Html;

/**
 * Widget for loading custom layout modal boxes.
 * 
 * @author  Gareth Palmer <gareth@one-space.co.za>
 */

class Modal extends Widget {

    /**
     * ### OPTIONAL
     * 
     * If static content of the modal box is desired, This property should contain
     * this content.
     * 
     * If both `$this->content` and `$this->link` is set, only `$this->content` will get loaded.
     * 
     * @var string  $content
     * 
     * @access  public
     */

    public string $content;


    /**
     * ### OPTIONAL
     * 
     * If dynamic content should be rendered as a `partialRender()`, this should contain
     * the link to that page.
     * 
     * If both `$this->content` and `$this->link` is set, only `$this->content` will get loaded.
     * 
     * ### Example
     * 
     * ```php
     * Url::to(['/announcement/announcement-render']);
     * ```
     * 
     * @var string  $link
     * 
     * @access  public
     */

    public string $link;

    /**
     * ### REQUIRED
     * 
     * The button or buttons (or whatever element), which, when clicked will invoke the modal.
     * 
     * ### Examples
     * 
     * - tr[data-view]
     * - #announcement-update
     * - .announcement-update
     * 
     * @var string  $button
     * 
     * @access  public
     */

    public string $button;

    /**
     * ### OPTIONAL
     * 
     * The title to put at the top of the modal box.
     * 
     * @var string  $title
     * 
     * @access  public
     */

    public string $title;

    /**
     * The overall id of the modal. Set dynamically so that more than one modal may exist on a page.
     * 
     * @var string  $id
     * 
     * @access  public
     */

    public string $id;

    private const DEFAULT_OPTIONS = [
        'class' => 'modal fade',
        'tabindex' => '-1',
        'role' => 'dialog',
        'aria-labelledby' => 'myModalLabel',
    ];

    public array $options = [];

    /**
     * Whether or not to overwrite the JS.
     * 
     * If you want to impliment your own modal loading script, set to true.
     * 
     * @var bool    $overwrite_js   Default: false
     * 
     * @access  public
     */

    public bool $overwrite_js = false;

    /**
     * Draw a larger size modal box.
     * 
     * @var bool    $large_modal    Default: false
     * 
     * @access  public
     */

    public bool $large_modal = false;


    /**
     * {@inheritdoc}
     * 
     * @access  public
     */

    public function init(): void {
        parent::init();
        $this->id ??= 'md' . Yii::$app->security->generateRandomString(8);

        if (!isset($this->link) && !isset($this->content)) {
            throw new Exception('link not set for modal.');
        }

        if (!isset($this->button) && !$this->overwrite_js) {
            throw new Exception('link not set for modal.');
        }
    }


    /**
     * {@inheritdoc}
     * 
     * @return  string
     * 
     * @access  public
     */
    public function run(): string {
        parent::run();

        $view = $this->getView();

        /**
         * Renders the bouncy logo when the content is slow loading.
         */

        $bounce = BounceLoader::widget();

        $modal = '';

        $options = self::DEFAULT_OPTIONS;
        foreach ($this->options as $key => $value) {
            switch ($key) {
                case 'class':
                    $options['class'] .= " {$value}";
                    break;
                default:
                    $options[$key] = $value;
            }
        }
        $options['id'] = $this->id;

        $modal .= Html::beginTag('div', $options);

        $size = '';
        if ($this->large_modal) {
            $size = ' modal-lg';
        }
        $modal .= "<div class='modal-dialog{$size}' role='document'>";
        $modal .= '<div class="modal-content">';

        $modal .= '<div class="modal-header">';
        $modal .= '<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>';
        if (isset($this->title)) {
            $modal .= "<h4 class='modal-title' id='myModalLabel'>{$this->title}</h4>";
        }
        $modal .= '</div>';

        if (isset($this->content)) {
            $modal .= '<div class="modal-body">' . $this->content . '</div>';
        } else {
            $modal .= '<div class="modal-body">' . $bounce . '</div>';
        }

        $modal .= '<div class="modal-footer">';
        $modal .= '<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>';
        $modal .= '</div>';

        $modal .= '</div></div></div>';

        if (!$this->overwrite_js) {
            if (isset($this->content)) {
                /**
                 * STATIC CONTENT
                 */
                $view->registerJs(<<<JS
                $(document).ready(function() {
                    $('{$this->button}').click(function() {
                        $('#{$this->id}').modal('show');
                    });
                });
                JS);
            } else {
                /**
                 * DYNAMIC CONTENT LOADED FROM THE DATA ON THE ELEMENT.
                 * 
                 * Any params should be parsed as JSON encoded on the data-data property
                 */
                $view->registerJs(<<<JS
                $(document).ready(function() {
                    $('{$this->button}').click(function() {
                        var itemdata = $(this).data('data');
                        $.get('$this->link', itemdata, function(data) {
                            $('#{$this->id} .modal-body').html(data);
                            $('#{$this->id}').modal('show');
                            /**
                             * @todo    Figure out form validation!!!
                             */
                        });
                    });
                    // Remove contents on close
                    $('#{$this->id}').on('hidden.bs.modal', function() {
                        $('#{$this->id} .modal-body').html(`$bounce`);
                    });
                });
                JS);
            }
        }
        return $modal;
    }
}
