/**
 * CodeDropz Uploader
 * Copyright 2018 Glen Mongaya
 * CodeDrop Drag & Drop Uploader
 * @version 1.0.0
 * @author CodeDropz, Glen Don L. Mongaya
 * @license The MIT License (MIT)
 */

// CodeDropz Drag and Drop Plugin
(function() {

    const EASYFUA_CodeDropz_Uploader = function( settings ) {

        // Parent input file type
        var input = this;

        // Define default options
        const defaultOptions = {
            handler: input,
            color: '#000',
            background: '',
            server_max_error: 'Uploaded file exceeds the maximum upload size of your server.',
            max_file: input.dataset.max ? input.dataset.max : 5, // default 5
            max_upload_size: input.dataset.limit ? input.dataset.limit : '5242880', // should be a bytes it's (5MB)
            supported_type: input.dataset.type ? input.dataset.type : 'jpg|jpeg|JPG|png|gif|pdf|doc|docx|ppt|pptx|odt|avi|ogg|m4a|mov|mp3|mp4|mpg|wav|wmv|xls',
            text: 'Drag & Drop Files Here',
            separator: 'or',
            button_text: 'Browse',
            on_success: '',
        };

        // Merge options with default options
        const options = Object.assign({}, defaultOptions, settings);

        // Get storage name
        var dataStorageName = input.dataset.name + '_count_files';

        // File Counter
        localStorage.setItem( dataStorageName, 1);

        // Template Container
        const cdropz_template = `
            <div class="codedropz-upload-handler">
                <div class="codedropz-upload-container">
                <div class="codedropz-upload-inner">
					<span class="easyfua-placeholder"></span>
                    <${easyfua_uploader.drag_n_drop_upload.tag}>${options.text}</${easyfua_uploader.drag_n_drop_upload.tag}>
                    <div class="codedropz-btn-wrap">
						<span>${options.separator}</span>
						<a class="cd-upload-btn" href="#">${options.button_text}</a>
					</div>
                </div>
                </div>
                <span class="dnd-upload-counter"><span>0</span> ${easyfua_uploader.dnd_text_counter} ${parseInt(options.max_file)}</span>
            </div>
        `;

        // Wrap input fields
        const wrapper = document.createElement('div');

        // Begin to wrap upload fields
        wrapper.classList.add('codedropz-upload-wrapper');
        options.handler.parentNode.insertBefore(wrapper, options.handler);
        wrapper.appendChild(options.handler);

        // Remove special character
        options.supported_type = options.supported_type.replace(/[^a-zA-Z0-9| ]/g, "");

        // Element Handler
        const form_handler = options.handler.closest('form');
        const options_handler = options.handler.closest('.codedropz-upload-wrapper');
        const btnOBJ = form_handler.querySelector('input[type="submit"], button[type="submit"]');

        // Append Format
        options.handler.insertAdjacentHTML('afterend', cdropz_template);

        // preventing the unwanted behaviours
        ['drag', 'dragstart', 'dragend', 'dragover', 'dragenter', 'dragleave', 'drop'].forEach(function(eventName) {
            options_handler.querySelector('.codedropz-upload-handler').addEventListener(eventName, function(e) {
                e.preventDefault();
                e.stopPropagation();
            });
        });

        // dragover and dragenter - add class
        ['dragover', 'dragenter'].forEach(function(eventName) {
            options_handler.querySelector('.codedropz-upload-handler').addEventListener(eventName, function(e) {
                options_handler.querySelector('.codedropz-upload-handler').classList.add('codedropz-dragover');
            });
        });

        // dragleave dragend drop - remove class
        ['dragleave', 'dragend', 'drop'].forEach(function(eventName){
            options_handler.querySelector('.codedropz-upload-handler').addEventListener(eventName, function(e) {
                options_handler.querySelector('.codedropz-upload-handler').classList.remove('codedropz-dragover');
            });
        });

        // Browse button clicked
        options_handler.querySelector('.cd-upload-btn').addEventListener('click', function(e){
            // stops the default action of an element from happening
            e.preventDefault();

            // Reset value
            options.handler.value = null;

            // Click input type[file] element
            options.handler.click();
        });

        // when dropping files
        options_handler.querySelector('.codedropz-upload-handler').addEventListener('drop', function(event) {
            // Run the uploader
            DND_Setup_Uploader(event.dataTransfer.files, 'drop');
        });

        // Trigger when input type[file] is click/changed
        options.handler.addEventListener('change', function(e) {
            // Run the uploader
            DND_Setup_Uploader(this.files, 'click');
        });

        // Remove accept attribute on mobile devices
        if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
            input.removeAttribute('accept');
        }

        // Setup Uploader
        var DND_Setup_Uploader = function( files, action ) {

            // make sure we have files
            if (files.length == 0 ) return;

            // gathering the form data
            var formData = new FormData();

            // Append file
            formData.append('action', 'easyfua_upload' );
            formData.append('type', action );
            formData.append('security', easyfua_uploader.ajax_nonce );

            // Upload field name & cf7 id
            formData.append('upload_name', input.dataset.name);

            // remove has error
            const errorHandler           = options.handler.querySelector('.has-error');
			const CodeDropzUploadElement = options_handler.querySelector('.codedropz-upload-handler');

            if (errorHandler) {
                errorHandler.remove();
            }

            // Loop files
            for (const file of files) {

                // Reset upload file type
                if( typeof formData.delete !== 'undefined' ) {
                    formData.delete('upload-file');
                }

                // Limit file upload
                if( Number( localStorage.getItem(dataStorageName) ) > options.max_file ) {
                    var hasErrorMsg = options_handler.querySelector('span.has-error-msg');
                    if (!hasErrorMsg) {
                        var err_msg = easyfua_uploader.drag_n_drop_upload.max_file_limit;
                        var errorMsgEl = document.createElement('span');
                        errorMsgEl.className = 'has-error-msg';
                        errorMsgEl.textContent = err_msg.replace('%count%', options.max_file);
						CodeDropzUploadElement.parentNode.insertBefore( errorMsgEl, CodeDropzUploadElement.nextSibling );
                    }
                    return false;
                }


                // Create progress bar
                const progressBarID = CodeDropz_Object.createProgressBar( file );
                var has_error = false;

                // File size limit - validation
                if (file.size > options.max_upload_size) {
                    const parentProgressBar = document.getElementById(progressBarID);
                    const errorSpan = document.createElement('span');
                    errorSpan.classList.add('has-error');
                    errorSpan.textContent = easyfua_uploader.drag_n_drop_upload.large_file;
                    parentProgressBar.querySelector('.dnd-upload-details').appendChild(errorSpan);
                    has_error = true;
                }

                // Validate file type
                regex_type = new RegExp("(.*?)\.("+ options.supported_type +")$");
                if ( has_error === false && !( regex_type.test( file.name.toLowerCase() ) ) ) {
                    document.querySelector('#' + progressBarID + ' .dnd-upload-details').insertAdjacentHTML('beforeend', '<span class="has-error">' + easyfua_uploader.drag_n_drop_upload.invalid_type + '</span>');
                    has_error = true;
                }

                // Increment count
                localStorage.setItem( dataStorageName, ( Number( localStorage.getItem( dataStorageName ) ) + 1 ) );

                // Make sure there's no error
                if( has_error === false ) {

					//alert(progressBarID);

                    // Append file
                    formData.append('upload-file', file );

                    // Process ajax upload
                    var xhr = new XMLHttpRequest();

                    // Get progress bar element
                    let progressBar = document.getElementById( progressBarID );
                    let progressElement = progressBar.querySelector('.dnd-progress-bar');
                    let detailsElement = progressBar.querySelector('.dnd-upload-details');
                    let submitButton = form_handler.querySelector('input[type="submit"], button[type="submit"]');

                    xhr.open(form_handler.getAttribute('method'), options.ajax_url);
                    xhr.onreadystatechange = function() {
                        if (this.readyState === 4) {
                            if (this.status === 200) {
                                var response = JSON.parse(this.responseText);
                                if (response.success) {

                                    // Complete the progress bar
                                    CodeDropz_Object.setProgressBar(progressBarID, 100);

                                    // Callback on success
                                    if (typeof options.on_success === "function") {
                                        options.on_success.call(this, input, progressBarID, response);
                                    }

                                } else {
                                	progressElement.remove();
                                    detailsElement.insertAdjacentHTML('beforeend', '<span class="has-error">'+ response.data +'</span>');
                                    if( submitButton ){
                                        submitButton.classList.remove('disable');
                                        submitButton.removeAttribute('disabled');
                                    }
                                    progressBar.classList.remove('in-progress');
                                }
                            } else {
                                progressElement.remove();
                                detailsElement.insertAdjacentHTML('beforeend', '<span class="has-error">'+ options.server_max_error +'</span>');
                                if( submitButton ){
                                    submitButton.classList.remove('disable');
                                    submitButton.removeAttribute('disabled');
                                }
                                progressBar.classList.remove('in-progress');
                            }
                        }
                    };
                    xhr.upload.addEventListener("progress", function(event){
                        if ( event.lengthComputable ) {

                            var percentComplete = ( event.loaded / event.total );
                            var percentage = parseInt( percentComplete * 100 );

                            // Make progress on the loading
                            CodeDropz_Object.setProgressBar( progressBarID, percentage - 1 );
                        }
                    }, false);

                    xhr.send(formData);

                }
            }

        }
        // End of Uploader function

        // CodeDropz object and functions
        var CodeDropz_Object = {

            // Create progress bar
            createProgressBar : function( file ) {

                // Setup progress bar variable
                var upload_handler = options_handler.querySelector('.codedropz-upload-handler');
                var generated_ID = 'dnd-file-' + Math.random().toString(36).substr(2, 9);

                // Setup progressbar elements
                var fileDetails = `
                    <div class="dnd-upload-image">
                        <span class="file"></span>
                    </div>
                    <div class="dnd-upload-details">
                        <span class="name"><span>${file.name}</span><em>(${CodeDropz_Object.bytesToSize(file.size)})</em></span>
                        <a href="#" title="${easyfua_uploader.drag_n_drop_upload.delete.title}" class="remove-file" data-storage="${dataStorageName}">
                        <span class="easyfua-icon-remove"></span>
                        </a>
                        <span class="dnd-progress-bar"><span></span></span>
                    </div>
                `;

                // Create new element and insert after upload_handler
                var statusElement = document.createElement('div');
                statusElement.id = generated_ID;
                statusElement.className = 'easyfua-upload-status';
                statusElement.innerHTML = fileDetails;
                upload_handler.parentNode.insertBefore(statusElement, upload_handler.nextSibling);

                return generated_ID;

            },

            // Process progressbar ( Animate progress )
            setProgressBar : function( progressBarID, percent ) {

                const progressBar = document.getElementById( progressBarID );
                const statusBar = progressBar.querySelector('.dnd-progress-bar');

                //console.log(statusbar);
                if (statusBar) {

                    // Disable submit button
                    if( btnOBJ ){
                        CodeDropz_Object.disableBtn(btnOBJ);
                    }

                    // Compute Progress bar
                    let progress_width = percent * statusBar.offsetWidth / 100;

                    // Set status bar in-progress
                    progressBar.classList.add('in-progress');

                    if (percent == 100) {
                        statusBar.querySelector('span').style.width = '100%';
                        statusBar.querySelector('span').textContent = `${percent}% `;
                    } else {
                        statusBar.querySelector('span').style.width = progress_width + 'px';
                        statusBar.querySelector('span').textContent = `${percent}% `;
                    }

                    if (percent == 100) {
                        progressBar.classList.add('complete');
                        progressBar.classList.remove('in-progress');
                    }
                }
                return false;

            },

            // Size Conversion
            bytesToSize : function( bytes ) {

                if( bytes === 0 )
                    return '0';

                kBytes = (bytes / 1024);
                fileSize = ( kBytes >= 1024 ? ( kBytes / 1024 ).toFixed(2) + 'MB' : kBytes.toFixed(2) + 'KB' );

                return fileSize;
            },

            // Disable button
            disableBtn : function( BtnOJB ) {
                if( BtnOJB  ) {
                    BtnOJB.classList.add('disable');
                    BtnOJB.disabled = true;
                }
            }
        };

	} // end fn.function

	// Generate & check nonce
	async function easyfua_nonce() {
		const res = await fetch(`${easyfua_uploader.ajax_url}?action=easyfua_rest_nonce`);
		const json = await res.json();
		if ( json.success ) {
			const nonce = json.data;
			if ( nonce.rest_nonce ) {
				easyfua_uploader.rest_nonce = nonce.rest_nonce;
			} else if( nonce.ajax ) {
				easyfua_uploader.ajax_nonce = nonce.ajax;
			}
		}
	}

	// Refresh and generate nonce on page load.
	document.addEventListener('DOMContentLoaded', () => {
		easyfua_nonce(); // run once on page load
		setInterval( easyfua_nonce, 3600000 ); // refresh every 1 hour
	});

    // Remove File
    document.addEventListener("click", function(e) {
        if( !e.target.classList.contains("easyfua-icon-remove") ) return;

		e.preventDefault();
        var _self = e.target,
            _dnd_status = _self.closest(".easyfua-upload-status"),
            _parent_wrap = _self.closest(".codedropz-upload-wrapper"),
            removeStorageData = _self.parentElement.getAttribute("data-storage"),
            storageCount = Number(localStorage.getItem(removeStorageData));

        // Direct remove the file if there's any error.
        if (_dnd_status.classList.contains("in-progress") || _dnd_status.querySelector(".has-error")) {
            _dnd_status.remove();
            localStorage.setItem(removeStorageData, storageCount - 1);
            return false;
        }

        // Change text Status
        _self.classList.add("deleting");
        _self.textContent = easyfua_uploader.drag_n_drop_upload.delete.text + "...";

        // Request ajax image delete
        var xhr = new XMLHttpRequest();
        xhr.open("POST", easyfua_uploader.ajax_url);
        xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        xhr.onload = function() {
            if (this.status === 200) {
                var response = JSON.parse(this.responseText);
                if (response.success) {

                    // Reduce file count and status bar element.
                    _dnd_status.remove();
                    localStorage.setItem(removeStorageData, storageCount - 1);

                    // Remove error msg
                    if ( _parent_wrap.querySelectorAll(".easyfua-upload-status").length <= 1 ){
                        if( _parent_wrap.querySelector(".has-error-msg") ){
                            _parent_wrap.querySelector(".has-error-msg").remove();
                        }
                    }

                    // Update Counter
                    _parent_wrap.querySelector(".dnd-upload-counter span").textContent = Number(localStorage.getItem(removeStorageData)) - 1;
                } else {
					const upload_details = _dnd_status.querySelector('.dnd-upload-details');
					if ( upload_details ) {
						const errorMsg = document.createElement('span');
						errorMsg.classList.add('has-error-msg');
						errorMsg.textContent = response.data;
						upload_details.appendChild( errorMsg );
					}
				}
            }
        };

        xhr.send(
            "path=" + _dnd_status.querySelector('input[type="hidden"]').value +
            "&action=easyfua_delete" +
            "&security=" + easyfua_uploader.ajax_nonce
        );

        document.querySelectorAll(".has-error-msg").forEach(function(el) {
            el.remove();
        });

    });

    // Attach CodeDropz_Uploader to HTMLElement prototype
    HTMLElement.prototype.EASYFUA_CodeDropz_Uploader = EASYFUA_CodeDropz_Uploader;

})();
// END: CodeDropz Uploader function

// Custom JS hook event
var dnd_upload_easyfua_event = function(target, name, data) {
	// Create a custom event with the specified name and data
	var event = new CustomEvent('dnd_upload_easyfua_' + name, {
		bubbles: true,
		detail: data
	});
	target.dispatchEvent(event);
}

// BEGIN: initialize upload
document.addEventListener('DOMContentLoaded', function() {

	window.EASYFUA_WP_initDragDrop = function () {

		// Get text object options/settings from localize script
		var TextOJB = easyfua_uploader.drag_n_drop_upload;
        var fileUpload = document.querySelectorAll('.easyfua_uploader');

        fileUpload.forEach(function(Upload) {

            // Support Multiple Fileds
            Upload.EASYFUA_CodeDropz_Uploader({
                'color': '#fff',
                'ajax_url': easyfua_uploader.ajax_url,
                'text': TextOJB.text,
                'separator': TextOJB.or_separator,
                'button_text': TextOJB.browse,
                'server_max_error': TextOJB.server_max_error,
                'on_success': function(input, progressBar, response) {

                    // Progressbar Object
                    var progressDetails = document.querySelector('.codedropz-upload-wrapper #' + progressBar);
                    var form = input.closest('form');

                    // If it's complete remove disabled attribute in button
					const submitButton = form.querySelector('button[type=submit], input[type=submit]');
					if( submitButton ){
						submitButton.classList.remove('disable');
						submitButton.removeAttribute('disabled');
					}

                    // Append hidden input field
                    var detailsElement = progressDetails.querySelector('.dnd-upload-details');
                    var inputHTML = '<span><input type="hidden" name="' + input.dataset.name + '_files[]" value="' + response.data.file + '"></span>';
                    detailsElement.insertAdjacentHTML('beforeend', inputHTML);

                    // Update counter
                    var filesCounter = ( Number( localStorage.getItem( input.dataset.name + '_count_files' ) ) - 1);
                    var counterElement = input.closest('.codedropz-upload-wrapper').querySelector('.dnd-upload-counter span');
                    counterElement.textContent = filesCounter;

					// Add custom event
					dnd_upload_easyfua_event( progressDetails, 'success', response );
                }
            });

        });

	}

	// Initialize drag & drop.
	window.EASYFUA_WP_initDragDrop();
});

// Handle form submission
const easyfua_button = document.getElementById('easyfua-submit');

// Confirmation status
let statusTimeout;

// Button submit is clicked.
easyfua_button.addEventListener('click', (e) => {
	e.preventDefault();

	// Const variable
	const easyfua_form = e.target.closest('form');
	const submitField  = easyfua_form.querySelector('.easyfua-submit-field');
	const statusEl     = easyfua_form.querySelector('.easyfua-status');
	const preLoader    = easyfua_form.querySelector('.easyfua-loader');
	const submitBtn    = e.target;

	// Return if the button is currently disabled.
	if ( submitBtn.disabled ) {
		return;
	}

	// Disabled submit button.
    submitBtn.disabled = true;

	// Remove status element
	if ( statusEl ) {
		statusEl.remove();
	}

	// Remove error.
	easyfua_form.querySelectorAll(".easyfua-error").forEach(el => el.remove());

	// Hide loader
	preLoader.style.display = 'inline-block';

	// Clear status message.
	if ( statusTimeout ) clearTimeout( statusTimeout );

	// Google Recaptcha V3 - Check if Google reCAPTCHA site key is provided
	if ( easyfua_uploader.g_site_key ) {
		grecaptcha.ready( function() {
			grecaptcha.execute( easyfua_uploader.g_site_key, { action: 'submit' } )
				.then( token => easyfua_submit_form(token) )
		});
	} else {
		easyfua_submit_form('');
	}

	// Submit form
	function easyfua_submit_form( token ) {
		// Form data fields.
		const formData = new FormData( easyfua_form );

		// Append token in formData.
		if ( token ) {
			formData.append( 'easyfua-recaptcha-response', token );
		}

		// Begin requesting.
		fetch( easyfua_uploader.rest_api + 'submit-form', {
			method : "POST",
			headers: {
				"X-WP-Nonce" : easyfua_uploader.rest_nonce // Nonce
			},
			body: formData
		})
			.then( response => response.json() )
			.then( (response) => {
				let messageHTML = '';
				// Display error under each field.
				if ( ! response.success ) {
					if ( response.data.code == 'invalid_token' ) {
						messageHTML = `<span class="easyfua-status error">${response.data.message}</span>`;
					} else {
						response.data.forEach((item) => {
							if( item?.code || item.global ) {
								messageHTML = `<span class="easyfua-status error">${item.message || item.global}</span>`;
							} else if ( item.el && item.msg ) {
								const field = document.querySelector(item.el);
								if ( field ) {
									field.insertAdjacentHTML(
										"afterend",
										`<div class="easyfua-error">${item.msg}</div>`
									);
								}
							}
						});
					}
				} else {
					messageHTML = `<span class="easyfua-status success">${response.data}</span>`;
					easyfua_reset_form( easyfua_form ); // reset the form if success.
				}

				// Append before submit button & auto hide confirmation message after 5 seconds.
				if ( messageHTML ) {
					submitField.insertAdjacentHTML('afterend', messageHTML);
					statusTimeout = setTimeout(() => {
						const msg = easyfua_form.querySelector('.easyfua-status');
						if (msg) msg.remove();
					}, 5000);
				}
			})
			.catch( (error) => console.log(error) )
			.finally(() => {
				submitBtn.disabled = false;       // remove disabled
				preLoader.style.display = 'none'; // hide pre-loader
			});
	}
});

// Form input focus hide error.
document.addEventListener('DOMContentLoaded', () => {
	const form = document.querySelector('#easyfua-form');
	if ( ! form ) return;
	form.querySelectorAll( 'input' ).forEach( field => {
		field.addEventListener( 'input', () => {
			const error = field.parentElement.querySelector('.easyfua-error');
			if ( error ) {
				if ( field.value.trim() ) {
					error.style.display = 'none';
				} else {
					error.style.display = '';
				}
			}
		});
	});
});

// Hook after file upload - hide or remove validation error.
document.addEventListener( 'dnd_upload_easyfua_success', function( event ) {
	// code goes here.
})

// Fire after submission
function easyfua_reset_form( form ) {

	// Get input type file element
	var inputFile = form.querySelectorAll('#easyfua-uploader');
	var status = form.querySelectorAll('.easyfua-upload-status');
	var counter = form.querySelector('.dnd-upload-counter span');
	var error = form.querySelectorAll('span.has-error-msg');

	// Reset upload list for multiple fields
	if ( inputFile.length > 0 ) {
		inputFile.forEach( (input) => localStorage.setItem( input.getAttribute('data-name') + '_count_files', 1 ) ); // Reset file counts
	}

	// Remove status / progress bar
	if (status) {
		status.forEach((statEl) => statEl.remove());
	}

	if (counter) {
		counter.textContent = '0';
	}

	if (error) {
		error.forEach((errEl) => errEl.remove());
	}

	form.reset();

}