<?php

namespace GriffinForms\Frontend\Html\Forms\Fields;

final class InputUrl extends \GriffinForms\Frontend\Html\Forms\Fields\Format
{
    protected function formControl()
    {
        $html = '<input type="url"';
        $html .= 'class="' . $this->html_ids['formcontrol'] . ' form-control mb-1"';
        $html .= $this->requiredAttr();
        $html .= $this->placeholderAttr();
        $html .= $this->valueAttr();
        $html .= $this->readOnlyAttr();
        $html .= $this->disabledAttr();
        $html .= $this->autocompleteAttr();
        $html .= ' data-gf-formpage="' . absint($this->data['formpage']) . '">';
        return $html;
    }
    
    protected function setErrors()
    {
        $this->errors = array(
            'required',
            'url',
            'protocols',
            'restrictedtlds',
            'excludedtlds',
            'pattern',
            'unique',
            'dbValidate'
        );
    }
    
    protected function isUrl()
    {
        return true;
    }
    
    protected function isProtocols()
    {
        if (key_exists('protocols', $this->validations) and !empty($this->validations['protocols'])) {
            return true;
        } else {
            return false;
        }
    }
    
    protected function isRestrictedTlds()
    {
        if (key_exists('restricted_tld', $this->validations) and !empty($this->validations['restricted_tld'])) {
            return true;
        } else {
            return false;
        }
    }
    
    protected function isExcludedTlds()
    {
        if (key_exists('excluded_tld', $this->validations) and !empty($this->validations['excluded_tld'])) {
            return true;
        } else {
            return false;
        }
    }
    
    protected function urlJs($error)
    {
        // Declare whether protocol validation is active
        $has_protocol_check = $this->isProtocols() ? 'true' : 'false';
        echo '
            $(actionBtn).hover(function(){
                $(formControl).each(checkUrl);
            });
            $(formControl).keyup(checkUrl);
            
            function checkUrl() {
                let value = $.trim($(this).val());

                // Skip validation for empty input
                if (value === "") {
                    removeAlert($(this), "' . esc_js($error) . '");
                    return;
                }

                const requireProtocol = ' . esc_js($has_protocol_check) . ';

                // Default to original input
                let testValue = value;

                // If protocol check is disabled, allow protocol-less URLs that resemble valid domains
                if (
                    !requireProtocol &&
                    !value.includes("://") &&
                    /^(https?:\/\/)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}(\/[^\s]*)?$/.test(value)
                ) {
                    testValue = "http://" + value;
                }

                // Validate using native URL constructor
                try {
                    new URL(testValue);
                    removeAlert($(this), "' . esc_js($error) . '");
                } catch(err) {
                    addAlert($(this), "' . esc_js($error) . '");
                }
            }
        ';
    }
    
    protected function protocolsJs($error)
    {
        echo '
            $(actionBtn).hover(function(){
                $(formControl).each(checkProtocols);
            });
            $(formControl).keyup(checkProtocols);
            
            function checkProtocols() {
                let value = $.trim($(this).val());
                        
                if(value === "") {
                    removeAlert($(this), "' . esc_js($error) . '");
                    return;
                }

                // List of allowed protocols as lowercase, used for prefix validation
                const protocols = ["' . implode('","', array_map('esc_js', array_map('strtolower', $this->validations['protocols']))) . '"];
                
                let i = 0;
                
                $.each(protocols, function(index, protocol){
                    if (value.toLowerCase().startsWith(protocol + "://")) {
                        i++;
                    }
                });
                if (i === 0) {
                    addAlert($(this), "' . esc_js($error) . '");
                } else {
                    removeAlert($(this), "' . esc_js($error) . '");
                }
            }
        ';
    }
    
    protected function restrictedTldsJs($error)
    {
        echo '
            $(actionBtn).hover(function(){
                $(formControl).each(checkRestrictedTlds);
            });

            $(formControl).keyup(checkRestrictedTlds);
            
            function checkRestrictedTlds() {
                        
                let value = $.trim($(this).val());

                if(value === "") {
                    removeAlert($(this), "' . esc_js($error) . '");
                    return;
                }

                const tlds = ["' . implode('","', array_map('esc_js', $this->validations['restricted_tld'])) . '"];
                
                let i = 0;
                
                $.each(tlds, function(index, tld) {
                    try {
                        const hostname = new URL(value).hostname;
                        // Check if hostname ends with .tld (case-insensitive)
                        if (hostname.toLowerCase().endsWith("." + tld.toLowerCase())) {
                            i++;
                        }
                    } catch (e) {}
                });

                if (i === 0) {
                    addAlert($(this), "' . esc_js($error) . '");
                } else {
                    removeAlert($(this), "' . esc_js($error) . '");
                }
            }
        ';
    }
    
    protected function excludedTldsJs($error)
    {
        echo '
            $(actionBtn).hover(function(){
                $(formControl).each(checkexcludedTlds);
            });
            $(formControl).keyup(checkexcludedTlds);
            
            function checkexcludedTlds() {

                let value = $.trim($(this).val());
                        
                if(value === "") {
                    removeAlert($(this), "' . esc_js($error) . '");
                    return;
                }

                const tlds = ["' . implode('","', array_map('esc_js', $this->validations['excluded_tld'])) . '"];
                console.log("Excluded TLDs:", tlds);
                
                let i = 0;
                
                $.each(tlds, function(index, tld) {
                    if (tld === "") {
                        return;
                    }
                    try {
                        const hostname = new URL(value).hostname;
                        if (hostname.toLowerCase().endsWith("." + tld.toLowerCase())) {
                            i++;
                        }
                    } catch (e) {}
                });

                if (i === 0) {
                    removeAlert($(this), "' . esc_js($error) . '");
                } else {
                    addAlert($(this), "' . esc_js($error) . '");
                }
            }
        ';
    }
}