<?php

namespace GriffinForms\Admin\Html\FormControls\Field\ValidationTraits;

trait InputPassword
{
    protected $password_min_length;
    protected $password_max_length;
    protected $password_allowed_sets = array();
    protected $password_required_sets = array();
    protected $password_disallowed_chars;
    protected $password_strength_requirement;
    protected $password_messages = array();

    protected function setPasswordValidationDefaults()
    {
        $this->password_min_length = $this->fixEmptyValue('min', '');
        $this->password_max_length = $this->fixEmptyValue('max', '');

        $allowed_sets = isset($this->value['allowed_sets']) && is_array($this->value['allowed_sets']) ? $this->value['allowed_sets'] : array();
        $required_sets = isset($this->value['required_sets']) && is_array($this->value['required_sets']) ? $this->value['required_sets'] : array();

        $valid_sets = $this->passwordCharacterSetKeys();

        $this->password_allowed_sets = array_values(array_intersect($allowed_sets, $valid_sets));
        if (empty($this->password_allowed_sets)) {
            $this->password_allowed_sets = array('uppercase', 'lowercase', 'numbers', 'symbols');
        }

        $this->password_required_sets = array_values(array_intersect($required_sets, $valid_sets));
        $this->password_disallowed_chars = $this->fixEmptyValue('disallowed_chars', '');

        $allowed_strength = array('weak', 'medium', 'strong', 'very_strong');
        $strength = $this->fixEmptyValue('min_strength', 'weak');
        $this->password_strength_requirement = in_array($strength, $allowed_strength, true) ? $strength : 'medium';

        $this->password_messages = isset($this->value['messages']) && is_array($this->value['messages'])
            ? array_map('sanitize_text_field', $this->value['messages'])
            : array();
    }

    protected function passwordCharacterSetKeys()
    {
        return array('uppercase', 'lowercase', 'numbers', 'symbols', 'spaces');
    }

    protected function passwordMessageValue($key, $fallback_key)
    {
        if (isset($this->password_messages[$key]) && $this->password_messages[$key] !== '') {
            return $this->password_messages[$key];
        }

        return $this->lang->getText($fallback_key);
    }

    protected function validationOptionsInputPassword()
    {
        $this->setPasswordValidationDefaults();

        echo '<div class="row">';

        echo '<div class="col-md-12 mb-3 gf-validation-options" id="gf-pattern-wrap">';
        $this->patternField();
        echo '</div>';

        echo '<div class="col-md-12 gf-validation-options" id="gf-custom-parameters-wrap">';

        echo '<div class="mb-4 border-bottom pb-4">';
        echo '<h6 class="fw-semibold">' . esc_html($this->lang->getText('password_rules_section', 'label')) . '</h6>';
        $this->passwordMinMaxFields();
        echo '</div>';

        echo '<div class="mb-4 border-bottom pb-4">';
        echo '<h6 class="fw-semibold">' . esc_html($this->lang->getText('password_allowed_section', 'label')) . '</h6>';
        $this->passwordAllowedSetsField();
        echo '</div>';

        echo '<div class="mb-4 border-bottom pb-4">';
        echo '<h6 class="fw-semibold">' . esc_html($this->lang->getText('password_required_section', 'label')) . '</h6>';
        $this->passwordRequiredSetsField();
        echo '</div>';

        echo '<div class="mb-4 border-bottom pb-4">';
        echo '<h6 class="fw-semibold">' . esc_html($this->lang->getText('password_disallowed_section', 'label')) . '</h6>';
        $this->passwordDisallowedCharsField();
        echo '</div>';

        echo '<div class="mb-4 border-bottom pb-4">';
        echo '<h6 class="fw-semibold">' . esc_html($this->lang->getText('password_strength_section', 'label')) . '</h6>';
        $this->passwordStrengthRequirementField();
        echo '</div>';

        echo '</div>';
        echo '</div>';
    }

    protected function passwordMinMaxFields()
    {
        echo '<div class="row g-3 align-items-start">';

        echo '<div class="col-md-12">';
        $min_field = new \GriffinForms\Admin\Html\FormControls\InputNumber('password_min_length', $this->password_min_length);
        $min_field->setAttr('min', 1);
        echo '<label class="d-block" for="' . esc_attr($min_field->elementId()) . '">' . esc_html($this->lang->getText('password_min_length', 'label')) . '</label>';
        $min_field->html();
        echo '<p class="description">' . esc_html($this->lang->getText('password_min_length', 'description')) . '</p>';
        $min_message = new \GriffinForms\Admin\Html\FormControls\InputText(
            'password_messages_min',
            $this->passwordMessageValue('min', 'password_min_message_default')
        );
        echo '<label class="d-block" for="' . esc_attr($min_message->elementId()) . '">' . esc_html($this->lang->getText('password_min_message', 'label')) . '</label>';
        $min_message->html();
        echo '</div>';

        echo '<div class="col-md-12 mt-3">';
        $max_field = new \GriffinForms\Admin\Html\FormControls\InputNumber('password_max_length', $this->password_max_length);
        $max_field->setAttr('min', 1);
        echo '<label class="d-block" for="' . esc_attr($max_field->elementId()) . '">' . esc_html($this->lang->getText('password_max_length', 'label')) . '</label>';
        $max_field->html();
        echo '<p class="description">' . esc_html($this->lang->getText('password_max_length', 'description')) . '</p>';
        $max_message = new \GriffinForms\Admin\Html\FormControls\InputText(
            'password_messages_max',
            $this->passwordMessageValue('max', 'password_max_message_default')
        );
        echo '<label class="d-block" for="' . esc_attr($max_message->elementId()) . '">' . esc_html($this->lang->getText('password_max_message', 'label')) . '</label>';
        $max_message->html();
        echo '</div>';

        echo '</div>';
    }

    protected function passwordAllowedSetsField()
    {
        $labels = array(
            'uppercase' => $this->lang->getText('password_charset_uppercase'),
            'lowercase' => $this->lang->getText('password_charset_lowercase'),
            'numbers'   => $this->lang->getText('password_charset_numbers'),
            'symbols'   => $this->lang->getText('password_charset_symbols'),
            'spaces'    => $this->lang->getText('password_charset_spaces'),
        );

        echo '<p class="components-base-control__label">' . esc_html($this->lang->getText('password_allowed_sets', 'label')) . '</p>';
        echo '<div id="griffinforms-password-allowedsets" class="griffinforms-checkbox-group">';

        foreach ($labels as $key => $label) {
            $checked = in_array($key, $this->password_allowed_sets, true) ? ' checked' : '';
            echo '<div class="components-base-control components-checkbox-control">';
            echo '<div class="components-base-control__field">';
            echo '<span class="components-checkbox-control__input-container">';
            echo '<input type="checkbox" class="components-checkbox-control__input" id="griffinforms-allowed-' . esc_attr($key) . '" name="password_allowed_sets[]" value="' . esc_attr($key) . '"' . esc_attr($checked) . '>';
            echo '</span>';
            echo '<label class="components-checkbox-control__label" for="griffinforms-allowed-' . esc_attr($key) . '">';
            echo esc_html($label);
            echo '</label>';
            echo '</div>';
            echo '</div>';
        }

        echo '</div>';
        echo '<p class="description">' . esc_html($this->lang->getText('password_allowed_sets', 'description')) . '</p>';

        echo '<div class="components-base-control components-text-control">';
        $message_field = new \GriffinForms\Admin\Html\FormControls\InputText(
            'password_messages_allowed_sets',
            $this->passwordMessageValue('allowed_sets', 'password_allowed_message_default')
        );
        echo '<label class="d-block" for="' . esc_attr($message_field->elementId()) . '">' . esc_html($this->lang->getText('password_allowed_message', 'label')) . '</label>';
        $message_field->html();
        echo '</div>';
    }

    protected function passwordRequiredSetsField()
    {
        $labels = array(
            'uppercase' => $this->lang->getText('password_charset_uppercase'),
            'lowercase' => $this->lang->getText('password_charset_lowercase'),
            'numbers'   => $this->lang->getText('password_charset_numbers'),
            'symbols'   => $this->lang->getText('password_charset_symbols'),
        );

        echo '<p class="components-base-control__label">' . esc_html($this->lang->getText('password_required_sets', 'label')) . '</p>';
        echo '<div id="griffinforms-password-requiredsets" class="griffinforms-checkbox-group">';

        foreach ($labels as $key => $label) {
            $checked = in_array($key, $this->password_required_sets, true) ? ' checked' : '';
            echo '<div class="components-base-control components-checkbox-control">';
            echo '<div class="components-base-control__field">';
            echo '<span class="components-checkbox-control__input-container">';
            echo '<input type="checkbox" class="components-checkbox-control__input" id="griffinforms-required-' . esc_attr($key) . '" name="password_required_sets[]" value="' . esc_attr($key) . '"' . esc_attr($checked) . '>';
            echo '</span>';
            echo '<label class="components-checkbox-control__label" for="griffinforms-required-' . esc_attr($key) . '">';
            echo esc_html($label);
            echo '</label>';
            echo '</div>';
            echo '</div>';
        }

        echo '</div>';
        echo '<p class="description">' . esc_html($this->lang->getText('password_required_sets', 'description')) . '</p>';

        $this->passwordRequirementMessageField('password_messages_require_uppercase', 'password_require_uppercase_message', 'require_uppercase');
        $this->passwordRequirementMessageField('password_messages_require_lowercase', 'password_require_lowercase_message', 'require_lowercase');
        $this->passwordRequirementMessageField('password_messages_require_number', 'password_require_number_message', 'require_number');
        $this->passwordRequirementMessageField('password_messages_require_symbol', 'password_require_symbol_message', 'require_symbol');
    }

    protected function passwordRequirementMessageField($control_name, $lang_key, $lookup_key)
    {
        echo '<div class="components-base-control components-text-control mt-3">';
        $field = new \GriffinForms\Admin\Html\FormControls\InputText(
            $control_name,
            $this->passwordMessageValue($lookup_key, $lang_key . '_default')
        );
        echo '<label class="d-block" for="' . esc_attr($field->elementId()) . '">' . esc_html($this->lang->getText($lang_key, 'label')) . '</label>';
        $field->html();
        echo '</div>';
    }

    protected function passwordDisallowedCharsField()
    {
        echo '<div class="components-base-control components-text-control">';
        echo '<label class="d-block" for="griffinforms-password_disallowed_chars-inputtext">' . esc_html($this->lang->getText('password_disallowed_chars', 'label')) . '</label>';
        $field = new \GriffinForms\Admin\Html\FormControls\InputText('password_disallowed_chars', $this->password_disallowed_chars);
        $field->html();
        echo '<p class="description">' . esc_html($this->lang->getText('password_disallowed_chars', 'description')) . '</p>';
        echo '</div>';

        $message_field = new \GriffinForms\Admin\Html\FormControls\InputText(
            'password_messages_disallowed_chars',
            $this->passwordMessageValue('disallowed_chars', 'password_disallowed_message_default')
        );
        echo '<div class="components-base-control components-text-control mt-3">';
        echo '<label class="d-block" for="' . esc_attr($message_field->elementId()) . '">' . esc_html($this->lang->getText('password_disallowed_message', 'label')) . '</label>';
        $message_field->html();
        echo '</div>';
    }

    protected function passwordStrengthRequirementField()
    {
        $options = array(
            'weak'        => $this->lang->getText('password_strength_weak'),
            'medium'      => $this->lang->getText('password_strength_medium'),
            'strong'      => $this->lang->getText('password_strength_strong'),
            'very_strong' => $this->lang->getText('password_strength_very_strong'),
        );

        echo '<label class="d-block" for="griffinforms-password_strength-selectfield">' . esc_html($this->lang->getText('password_min_strength', 'label')) . '</label>';
        $select = new \GriffinForms\Admin\Html\FormControls\SelectField('password_min_strength', $this->password_strength_requirement);
        $select->selectOptions($options);
        $select->html();
        echo '<p class="description">' . esc_html($this->lang->getText('password_min_strength', 'description')) . '</p>';

        $message_field = new \GriffinForms\Admin\Html\FormControls\InputText(
            'password_messages_min_strength',
            $this->passwordMessageValue('min_strength', 'password_strength_message_default')
        );
        echo '<div class="components-base-control components-text-control mt-3">';
        echo '<label class="d-block" for="' . esc_attr($message_field->elementId()) . '">' . esc_html($this->lang->getText('password_strength_message', 'label')) . '</label>';
        $message_field->html();
        echo '</div>';
    }
}
