<?php

namespace IMATHUZH\Qfq\Core\Renderer\FormElement\Bootstrap3;

use IMATHUZH\Qfq\Core\Form\FormElement\AbstractFormElement;
use IMATHUZH\Qfq\Core\Helper\HelperFormElement;
use IMATHUZH\Qfq\Core\Helper\Support;
use IMATHUZH\Qfq\Core\Renderer\BaseRenderer;
use IMATHUZH\Qfq\Core\Renderer\FormElement\Base\SelectRenderer;

class Bootstrap3SelectRenderer extends SelectRenderer {

    /**
     * @param AbstractFormElement $fe
     * @param string $renderMode
     * @return string
     * @throws \CodeException
     * @throws \UserFormException
     * @throws \UserReportException
     */
    public function renderInput(AbstractFormElement $fe, string $renderMode = RENDER_MODE_HTML): string {

        if (isset($fe->attributes[FE_SIZE]) && $fe->attributes[FE_SIZE] > 1) {
            return $this->renderMultiSelect($fe);
        }

        $option = '';
        $firstSelect = true;
        $jsonValues = array();
        $total = count($fe->itemValues);

        // selectBS
        $firstSelectText = '<span class="caret"></span>';
        $firstSelectValue = '';
        $dropdownElement = count($fe->itemGroupKeys) === 0 ? 'option' : 'li';
        $selectBS = ($dropdownElement === 'li');
        $style = '';
        $groupLevel = 0;


        for ($ii = 0; $ii < $total; $ii++) {

            $groupName = $fe->itemGroupValues[$ii] ?? '';

            // selectBS
            if ($groupName !== '') {
                $fe->attributes[FE_SELECT_BS] = 1;
                $previousGroupName = $fe->itemGroupValues[$ii - 1] ?? null;

                // group name or separator should be rendered
                if (is_null($previousGroupName) || $previousGroupName !== $groupName) {

                    // separator
                    if (substr_count($groupName, '|') !== 0 && !is_null($previousGroupName)) {
                        $class = 'class="divider qfq-item-disabled"';
                        $role = 'role="separator"';
                        $option .= "<li {$class} {$style} {$role}></li>";

                        // group name
                    } else if (substr_count($groupName, '|') === 0) {
                        $groupLevel = 0;
                        $style = 'style="padding-left:' . $groupLevel * 5 + 7 . 'px;"';
                        $class = 'class="qfq-item-disabled"';

                        // group name contains multiple parts
                        if (substr_count($groupName, '.') > 0) {
                            $groupNameArr = explode('.', $groupName);

                            // iterate through all parts of group name
                            foreach ($groupNameArr as $groupNamePart) {
                                $previousGroupNameArr = explode('.', $previousGroupName);

                                // group name part has not been used yet
                                if (!in_array($groupNamePart, $previousGroupNameArr)) {
                                    $style = 'style="padding-left:' . $groupLevel * 5 + 7 . 'px;"';
                                    $option .= "<li {$class} {$style}>{$groupNamePart}</li>";

                                    // group name part has already been used
                                } else {

                                    // get previous level based on index of array
                                    $groupLevel = array_search($groupNamePart, $previousGroupNameArr);
                                }

                                $groupLevel++;
                            }

                            // group name does not contain multiple parts
                        } else {
                            $option .= "<li {$class} {$style}>{$groupName}</li>";
                        }

                        $groupLevel++;
                    }
                }

                $style = 'style="padding-left:' . $groupLevel * 5 + 7 . 'px;"';
            }

            //Disable dropdown item for li and option
            $classArray = isset($fe->classValue[$ii]) ? preg_split('/\s+/', $fe->classValue[$ii], -1, PREG_SPLIT_NO_EMPTY) : [];
            if (in_array('disabled', $classArray) && $selectBS) {
                $class = 'class="qfq-dropdown-item-disabled"';
                $option .= "<{$dropdownElement} {$class} {$style}";
            } else {
                $option .= "<{$dropdownElement} {$style}";
            }

            $option .= Support::doAttribute('value', trim(strip_tags($fe->itemKeys[$ii])), false);

            if ($ii == 0 && $fe->attributes[FE_PLACEHOLDER] != '') {
                $option .= ' disabled hidden ';
            }

            if (in_array('disabled', $classArray) && !$selectBS) {
                $option .= 'disabled ';
            }

            // Build display text with optional count (only in filter mode)
            $displayText = $fe->itemValues[$ii];
            $isFilterMode = $fe->attributes[FE_INLINE_FILTER] ?? false;
            $countValue = $fe->itemCounts[$ii] ?? null;
            if ($isFilterMode && $countValue !== null) {
                $displayText .= ' (' . $countValue . ')';
                $option .= Support::doAttribute('data-count', $countValue, false);
            }

            $jsonValues[] = [
                HTML_ATTR_VALUE => $fe->itemKeys[$ii],
                HTML_ATTR_TEXT => $displayText,
                HTML_ATTR_SELECTED => ($fe->itemKeys[$ii] == $fe->value && $firstSelect),
            ];

            if (trim(strip_tags($fe->itemKeys[$ii])) == $fe->value && $firstSelect) {
                $option .= ($selectBS) ? 'data-selected class="qfq-item-focused"' : 'selected';
                $firstSelect = false;

                // selectBS
                $firstSelectText = $displayText . ' ' . '<span class="caret"></span>';
                $firstSelectValue = trim(strip_tags($fe->itemKeys[$ii]));
            }

            $option .= '>' . $displayText . "</{$dropdownElement}>";
        }

        //$wrapSetupClass = $this->wrap[WRAP_SETUP_ELEMENT][WRAP_SETUP_CLASS] ?? '';
        //$json = $this->getFormElementForJson($htmlFormElementName, $jsonValues, $formElement, $wrapSetupClass);

        $fe->attributes = HelperFormElement::prepareExtraButton($fe->attributes, true);

        if (isset($fe->attributes[HTML_ATTR_DATALIST])) {
            if ($fe->attributes[FE_DYNAMIC_UPDATE] === 'yes') {
                throw new \UserFormException("Datalist and dynamic update are not compatible", ERROR_NOT_IMPLEMENTED);
            }
            $fe->htmlAttributes[HTML_ATTR_LIST] = $fe->attributes[FE_HTML_ID] . '-datalist';
            $html = '<input ' . Support::arrayToXMLAttributes($fe->htmlAttributes) . '><datalist '
                . Support::doAttribute(HTML_ATTR_ID, $fe->htmlAttributes[HTML_ATTR_LIST]) . '>' . $option . '</datalist>';
        } else {
            // selectBS
            if ($selectBS) {
                $html = '<div class="qfq-select-bs-parent">
                         <input type="hidden" value="' . $firstSelectValue . '" ' . Support::arrayToXMLAttributes($fe->htmlAttributes) . '>
                         <button type="button" class="form-control btn btn-default qfq-select-bs-button" id="' . $fe->htmlAttributes['id'] . '-b">'
                    . $firstSelectText .
                    '</button>
                         <ul class="dropdown-menu qfq-select-bs-list">' . $option . '</ul></div>';
            } else {
                $selectClass = 'form-control custom-select ' . implode(' ', $fe->cssClasses);
                $html = '<select class="' . trim($selectClass) . '" ' . Support::arrayToXMLAttributes($fe->htmlAttributes) . '>' . $option . '</select>';
            }

            if (($fe->attributes[FE_TMP_EXTRA_BUTTON_HTML]??'') !== ''
                || (isset($fe->attributes[FE_INPUT_EXTRA_BUTTON_PASSWORD]) && $fe->attributes[FE_INPUT_EXTRA_BUTTON_PASSWORD] !== '')
                || (isset($fe->attributes[FE_INPUT_EXTRA_BUTTON_LOCK]) && $fe->attributes[FE_INPUT_EXTRA_BUTTON_LOCK] !== '')
                || (isset($fe->attributes[FE_INPUT_EXTRA_BUTTON_INFO]) && $fe->attributes[FE_INPUT_EXTRA_BUTTON_INFO] !== '')) {

                $html = Support::wrapTag('<div class="input-group">', $html . $fe->attributes[FE_TMP_EXTRA_BUTTON_HTML]);
            }
        }

        $html = $html . HelperFormElement::getHelpBlock();
        return $html . $fe->attributes[FE_INPUT_EXTRA_BUTTON_INFO];

    }

    private function renderMultiSelect($fe): string {
        $html = '';
        if (($fe->attributes[FE_DYNAMIC_UPDATE] ?? '') === 'yes') $fe->htmlAttributes[FE_DATA_LOAD] = 'data-load';

        $attributeBaseLabel = Support::doAttribute('style', 'min-width: ' . ($fe->attributes[F_FE_MIN_WIDTH] ?? 0) . 'px;');

        $checkboxClass = 'checkbox';
        $class = 'qfq-multi-select-container ' . implode(' ', $fe->cssClasses);
        $isFilterMode = $fe->attributes[FE_INLINE_FILTER] ?? false;

        if (($fe->attributes[FE_MODE] ?? '') == FE_MODE_READONLY) {
            $checkboxClass .= ' qfq-disabled'; // necessary for own style checkboxes to display them 'disabled'
            $class .= ' qfq-disabled';
        }

        for ($ii = 0, $jj = 1; $ii < count($fe->itemKeys); $ii++, $jj++) {
            $attribute = $fe->htmlAttributes;
            $htmlFormElementNameUniq = HelperFormElement::prependFormElementNameCheckBoxMulti($fe->htmlAttributes['name'], $ii, true);
            $attribute[HTML_ATTR_ID] = HelperFormElement::getCheckboxRadioOptionId($fe->attributes[FE_HTML_ID] ?? '', $ii);
            $attribute[HTML_ATTR_NAME] = $htmlFormElementNameUniq;
            $attribute[ATTRIBUTE_DATA_REFERENCE] = ($fe->attributes[FE_DATA_REFERENCE] ?? '') . '-' . $ii;

            if (isset($fe->attributes[FE_AUTOFOCUS])) {
                $attribute[FE_AUTOFOCUS] = $fe->attributes[FE_AUTOFOCUS];
                unset ($fe->attributes[FE_AUTOFOCUS]);
            }

            $attribute[HTML_ATTR_VALUE] = $fe->itemKeys[$ii];

            // Check if the given key is found in field.
            $values = explode(',', $fe->value); // Defines which of the checkboxes will be checked.
            if (false !== array_search($fe->itemKeys[$ii], $values)) {
                $attribute[FE_CHECKBOX_CHECKED] = FE_CHECKBOX_CHECKED;
            }

            // '&nbsp;' - This is necessary to correctly align an empty input.
            $valueShow = ($fe->itemValues[$ii] === '') ? '&nbsp;' : $fe->itemValues[$ii];

            // Add count if available (only in filter mode)
            $countValue = $fe->itemCounts[$ii] ?? null;
            if ($isFilterMode && $countValue !== null) {
                $valueShow .= ' (' . $countValue . ')';
                $attribute['data-count'] = $countValue;
            }

            $htmlElement = '<input ' . Support::arrayToXMLAttributes($attribute) . '>' . $valueShow . '<span class="checkmark" aria="hidden"></span>';

            $checkboxLabelId = HelperFormElement::getCheckboxRadioOptionId($fe->attributes[FE_HTML_ID] ?? '', $ii, HTML_ID_EXTENSION_LABEL);
            $htmlElement = Support::wrapTag("<label class=\"$checkboxClass\" $attributeBaseLabel id=\"$checkboxLabelId\">", $htmlElement, true);
            $html .= $htmlElement;
        }

        // Calc height
        $height = 'style="height:' . (($fe->attributes[FE_SIZE] ?? 5) * 2.7) . 'em;"';

        // Wrap with scrollable div
        $html = Support::wrapTag('<div id="'.$fe->htmlAttributes[HTML_ATTR_ID].'" ' . $height . ' class="'. trim($class) .'">', $html);

        $fe->attributes = HelperFormElement::prepareExtraButton($fe->attributes, true, 'btn-group-plain-bottom-right');
        $html .= $fe->attributes[FE_TMP_EXTRA_BUTTON_HTML] ?? '';

        if (($fe->attributes[FE_TMP_EXTRA_BUTTON_HTML] ?? '') !== '') {
            $html = Support::wrapTag('<div class="btn-group-plain-wrapper">', $html);
        }
        return $html . ($fe->attributes[FE_INPUT_EXTRA_BUTTON_INFO] ?? '');
    }
}