/**
 * This class handles the OTP functionality in the frontend
 */
class OTP {
    static restUrl = {};
    static nonce = '';
    static forms = [];
    static OTPCode = {}

    constructor(currentScript) {
        OTP.nonce = currentScript.getAttribute('data-nonce');
        OTP.restUrl = {
            generate: currentScript.getAttribute('data-rest-url') + 'nmb/v1/otp/generate',
            validate: currentScript.getAttribute('data-rest-url') + 'nmb/v1/otp/validate'
        }
        OTP.forms = document.querySelectorAll('form');
        OTP.OTPCode = {
            code: '',
            valid: false
        }
        this.init();
    }

    init() {
        OTP.forms.forEach((form, index) => {
            // Add OTP field to each form on load.
            this.addOTPModal(form, index);

            // Prevent submission of form if OTP is not valid
            form.addEventListener('submit', (event) => {
                event.preventDefault();
                if (OTP.OTPCode.valid) {
                    form.submit();
                } else {
                    OTP.generateOTP(form);
                }
            });
        });
    }


    /**
     * This adds the markup for the OTP modal to the dom.
     *
     * @param form  - the form element
     * @param index - index of the form in the forms array, this is used as an ID for the modal.
     */
    addOTPModal(form, index) {
        form.setAttribute('data-otp', OTP.nonce + index);
        const modal = `<div id="${OTP.nonce +  index}" class="nmb_otp-modal">
                            <div class="nmb_otp-modal-content">
                                <p>Enter the OTP value you have recieved over your email.</p>
                                <div class="userInput" data-otp="${OTP.nonce + index}">
                                    <input type="text" data-id='1' maxlength="1" onkeyup="OTP.clickEvent(this,'2')" />
                                    <input type="text" data-id="2" maxlength="1" onkeyup="OTP.clickEvent(this,'3')" />
                                    <input type="text" data-id="3" maxlength="1" onkeyup="OTP.clickEvent(this,'4')" />
                                    <input type="text" data-id="4" maxlength="1" onkeyup="OTP.clickEvent(this,'5')" />
                                    <input type="text" data-id="5" maxlength="1" onkeyup="OTP.clickEvent(this,'6')" />
                                    <input type="text" data-id="6" maxlength="1" onkeyup="OTP.clickEvent(this,false)" />
                                </div>
                                <div class="new-request" data-otp="${OTP.nonce + index}">
                                    <a href="#" class="nmb_otp-new-request" onclick="OTP.requestNewOTP(this)">Request a new OTP</a>
                                </div>
                            </div>
                        </div>`;
        form.insertAdjacentHTML('afterend', modal);
    }

    /**
     * This shows or hides the OTP modal.
     *)
     * @param form
     * @param show
     */
    static showHideModal(form, show = true) {
        const modalId = form.getAttribute('data-otp');
        const modal = document.getElementById(modalId);
        if (show) {
            modal.style.display = "block";
        } else {
            modal.style.display = "none";
        }
    }

    /**
     * Sends a request to get an OTP, sent to the email.
     *
     *
     * @param form
     */
    static generateOTP(form) {
        const emailField = form.querySelector('input[type="email"]');
        if (!emailField.value.length) {
            alert('Please enter an email address');
            return false;
        }
        const data = {
            email: emailField.value,
            nonce: OTP.nonce
        }
        fetch(OTP.restUrl.generate, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(data)
        })
            .then(response => response.json())
            .then(res => {
                if (res.response === 'success') {
                    OTP.showHideModal(form);
                }
            });
    }

    /**
     * Validates the OTP entered by the user.
     *
     * @param modalId
     */
    static validateOTP(modalId) {
        const modal = document.getElementById(modalId);
        const inputs = modal.querySelectorAll('input');
        const otpString = Array.from(inputs).map(input => input.value).join('');
        const data = {
            otpCode: otpString,
            nonce: OTP.nonce
        }
        fetch(OTP.restUrl.validate, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(data)
        }).then(response => response.json())
            .then(res => {
                if (res.response === 'success') {
                    OTP.OTPCode.code = otpString;
                    OTP.OTPCode.valid = true;
                    // Submit the form successfully.
                    const form = document.querySelector(`form[data-otp="${modalId}"]`);
                    console.log(form)
                    form.submit();
                } else {
                    alert('Invalid OTP');
                }
            });
    }

    /**
     * Request new OTP when clicked on it
     */
    static requestNewOTP(btn) {
        const formId = btn.parentNode.getAttribute('data-otp');
        const form = document.querySelector(`form[data-otp="${formId}"]`);
        OTP.generateOTP(form);
    }


    /**
     * List of helpers and utils for this class
     *
     */
    static clickEvent(current, next) {
        if (current.value.length) {
            if (next !== false) {
                // get parent
                const parent = current.parentNode;
                const input = parent.querySelector(`input[data-id="${next}"]`);
                input.value = '';
                input.focus();
                return;
            }

            const modalId = current.parentNode.getAttribute('data-otp');
            OTP.validateOTP(modalId);
        }
    }
}

///////////////////////////
// Entry Point
///////////////////////////
window.addEventListener('DOMContentLoaded', (event) => {
    const currentScript = document.currentScript || (function () {
        // get script with id 'no-more-bots'
        const scripts = document.getElementsByTagName('script');
        for (let i = scripts.length - 1; i >= 0; i--) {
            if (scripts[i].getAttribute('id') === 'no-more-bots') {
                return scripts[i];
            }
        }
    })();
    new OTP(currentScript);
})
