let SM = {
    redirectIfSafe: (target) => {
        if (typeof target !== 'string' || target === '') {
            window.location.assign('/');
            return;
        }

        let url;
        try {
            url = new URL(target, window.location.origin);
        } catch (error) {
            window.location.assign('/');
            return;
        }

        if (url.origin !== window.location.origin) {
            window.location.assign('/');
            return;
        }

        window.location.assign(url.href);
    },

    alert: (title, text, type = 'info') =>{
        const data = {
            position: 'top-end',
            timer: 7000,
            toast: true,
            title: title,
            text: text,
            showConfirmButton: false,
            showCloseButton: true,
            customClass: {
                container: type,
            }
        }

        Swal.fire(data);
    },

    confirm: (title, content, button, callback) => {
        Swal.fire({
            position: 'top',
            icon: 'warning',
            iconColor: '#b91c1c',
            title: title,
            html: content,
            showCancelButton: true,
            confirmButtonText: button,
            confirmButtonColor: '#b91c1c',
            cancelButtonText: 'Cancel',
            reverseButtons: true
        }).then((result) => {
            callback(result.isConfirmed);
        });
    },

    copyToClipboard: (text) => {
        const copyContent = async () => {
            try {
                await navigator.clipboard.writeText(text);
                SM.alert('Link copied', 'The link has been copied to the clipboard.', 'success');
            } catch (err) {
                SM.alert('Copy failed', 'Could not copy the link to the clipboard. It may not have permission in your browser.', 'danger');
            }
        }

        copyContent().then(() => { /* empty */});
    },

    updateShippingAddress: () => {
        const checkboxElement = document.querySelector('input[name="shipping_same_billing"]');

        if (checkboxElement) {
            const itemNames = ['address', 'address2', 'city', 'state', 'postcode', 'country'];

            if (checkboxElement.checked) {
                itemNames.forEach((itemName) => {
                    const element = document.querySelector(`input[name="shipping_${itemName}"]`);
                    element.value = document.querySelector(`input[name="billing_${itemName}"]`).value;
                    element.setAttribute('readonly', 'true');
                });
            } else {
                itemNames.forEach((itemName) => {
                    const element = document.querySelector(`input[name="shipping_${itemName}"]`);
                    element.removeAttribute('readonly');
                });
            }
        }
    },

    confirmDelete: (token, title, content, url) => {
        Swal.fire({
            position: 'top',
            icon: 'warning',
            iconColor: '#b91c1c',
            title: title,
            html: content,
            showCancelButton: true,
            confirmButtonText: 'Delete',
            confirmButtonColor: '#b91c1c',
            cancelButtonText: 'Cancel',
            reverseButtons: true
        }).then((result) => {
            if (result.isConfirmed) {
                axios.delete(url)
                .then((response) => {
                    if(response.data.success){
                        SM.redirectIfSafe(response.data.redirect);
                    }
                })
                .catch(() => {
                    window.location.reload();
                });
            }
        });
    },

    upload: (files, callback, titles = []) => {
        let uploadedFiles = [];

        if(files.length === 0) {
            return;
        }

        const data = {
            title: "Checking...",
            text: "Please wait",
            imageUrl: "/loading.gif",
            imageHeight: 100,
            showConfirmButton: false,
            allowOutsideClick: false,
            allowEscapeKey: false,
        }
        Swal.fire(data);

        const showError = (message) => {
            Swal.fire({
                position: 'top',
                icon: 'error',
                title: 'An error occurred',
                html: message,
                showConfirmButton: true,
                confirmButtonColor: '#b91c1c',
            }).then(() => {
                if(callback) {
                    callback({success: false});
                }
            });
        }

        for(const file of files) {
            if (file.size > SM.maxUploadSize()) {
                const size = SM.bytesToString(file.size);
                const maxSize = SM.bytesToString(SM.maxUploadSize());
                showError('The file size is too large (' + size + ').<br />Please upload a file less than ' + maxSize + '.');
                return;
            }
        }

        const uploadFile = (file, start, title, idx, count, uploadToken = null) => {
            const showPercentDecimals = (file.size > (1024 * 1024 * 40));
            const chunkSize = 1024 * 1024 * 2;
            const end = Math.min(file.size, start + chunkSize);
            const chunk = file.slice(start, end);

            const formData = new FormData();
            formData.append('file', chunk);
            formData.append('filename', file.name);
            formData.append('filesize', file.size);
            if (uploadToken) {
                formData.append('upload_token', uploadToken);
            }

            if (start === 0) {
                formData.append('filestart', 'true');
            } else {
                formData.append('fileappend', 'true');
            }

            if (title !== '') {
                formData.append('title', title);
            }

            axios.post('/admin/media', formData, {
                headers: {
                    'Content-Type': 'multipart/form-data',
                    'Accept': 'application/json'
                },
                onUploadProgress: (progressEvent) => {
                    let percent = ((start + progressEvent.loaded) / file.size) * 100;

                    if(showPercentDecimals) {
                        percent = percent.toFixed(1);
                    } else {
                        percent = Math.round(percent);
                    }

                    let title = 'Uploading';
                    if(count > 1) {
                        title += ' ' + (idx + 1) + ' of ' + count;
                    }

                    Swal.update({
                        title: title + '...',
                        html: `${file.name} - ${percent}%`,
                    });
                }
            }).then((response) => {
                if (response.status === 200) {
                    if (response.data && response.data.upload_token) {
                        uploadToken = response.data.upload_token;
                    }

                    if (end >= file.size) {
                        uploadedFiles.push({ file: file, title: title, data: response.data });

                        if (idx === count - 1) {
                            Swal.fire({
                                icon: 'success',
                                title: 'Success',
                                html: count > 1 ? `Uploaded ${count} files successfully` : `${response.data.name || file.name} uploaded successfully`,
                                showConfirmButton: false,
                                timer: 3000
                            });

                            if (callback) {
                                window.setTimeout(() => {
                                    callback({ success: true, files: uploadedFiles });
                                }, 3000);
                            }

                            return;
                        } else {
                            start = 0;
                            idx += 1;
                            uploadToken = null;
                        }
                    } else {
                        start = end;
                    }

                    uploadFile(files[idx], start, titles[idx] || '', idx, files.length, uploadToken);
                } else {
                    showError(response.data.message);
                }
            }).catch(() => {
                showError('An error occurred while uploading the file.');
            });
        }

        uploadFile(files[0], 0, titles[0] || '', 0, files.length);
    },

    bytesToString: (bytes) => {
        bytes = parseInt(bytes);
        if (isNaN(bytes)) {
            bytes = 0;
        }

        const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
        const fixed = [0, 0, 2, 2, 2];
        if (bytes === 0) return '0 Bytes';
        const i = Math.floor(Math.log(bytes) / Math.log(1024));
        const size = parseFloat((bytes / Math.pow(1024, i)).toFixed(fixed[i]));
        return size + ' ' + sizes[i];
    },

    maxUploadSize: () => {
        try {
            return parseInt(document.querySelector('meta[name="max-upload-size"]').getAttribute('content'));
        } catch (error) {
            /* Do nothing */
        }

        return 0;
    },

    /**
     * Transforms a string to title case.
     * @param {string} str The string to transform.
     * @returns {string} A string transformed to title case.
     */
    toTitleCase: (str) => {
        // Remove leading and trailing spaces
        str = str.trim();

        // Remove file extension
        str = str.replace(/\.[a-zA-Z0-9]{1,4}$/, "");

        // Replace underscores and hyphens with spaces
        str = str.replace(/[_-]+/g, " ");

        // Capitalize the first letter of each word and make the rest lowercase
        str = str.replace(/\b\w+\b/g, (txt) => {
            return txt.charAt(0).toUpperCase() + txt.slice(1).toLowerCase();
        });

        // Replace "cdn" with "CDN"
        str = str.replace(/\bCdn\b/gi, "CDN");

        return str;
    },

    mediaDetails: (name, callback) => {
        axios.get('/media/' + name, {
            headers: {
                'Accept': 'application/json'
            }
        }).then((response) => {
            callback(response.data);
        }).catch((error) => {
            console.error(error);
            callback(null);
        });
    },

    mimeMatches: (fileMime, matchMimeList) => {
        for(const matchMime of matchMimeList.split(',')) {
            if (matchMime === '*' || matchMime === '*/*') {
                return true;
            }

            const matchMimeArray = matchMime.split('/');
            const fileMimeArray = fileMime.split('/');

            if (matchMimeArray[1] === '*' && matchMimeArray[0] === fileMimeArray[0]) {
                return true;
            } else if(fileMime === matchMime) {
                return true;
            }
        }

        return false;
    },

    arrayToString: (array, separator = ',') => {
        return array.map(item => {
            if (item.includes(separator)) {
                // If the item contains the separator, wrap it in quotes and escape any quotes within the string
                return `"${item.replace(/"/g, '\\"')}"`;
            } else {
                return item;
            }
        }).join(separator);
    },

    stringToArray: (string, separator = ',') => {
        return string.split(separator).map(item => {
            // Remove quotes and unescape any escaped quotes within the string
            return item.replace(/^"|"$/g, '').replace(/\\"/g, '"');
        });
    },

    decodeHtml: (html) => {
        const ta = document.createElement("textarea");
        ta.innerHTML = html;
        return ta.value;
    },

    toLocalISOString: (date) => {
        return date.getFullYear() + '-' + (date.getMonth() + 1).toString().padStart(2, '0') + '-' + date.getDate().toString().padStart(2, '0') + 'T' + date.getHours().toString().padStart(2, '0') + ':' + date.getMinutes().toString().padStart(2, '0');
    },

    updateThumbnail: (name, element) => {
        axios.get('/media/' + name)
            .then(response => {
                if(response.data.status === 'ready') {
                    if(element instanceof HTMLImageElement) {
                        element.src = response.data.thumbnail;
                    } else if(typeof element === 'string') {
                        const imgElement = document.querySelector(element);
                        if(imgElement instanceof HTMLImageElement) {
                            imgElement.src = response.data.thumbnail;
                        }
                    }
                } else if(response.data.status === 'processing') {
                    setTimeout(() => {
                        SM.updateThumbnail(name, element);
                    }, 5000);
                }
            })
            .catch(error => {
                console.error(error);
            });
    },

    updateAllThumbnails: () => {
        const elements = document.querySelectorAll('img[data-thumbnail]');
        elements.forEach(element => {
            SM.updateThumbnail(element.getAttribute('data-thumbnail'), element);
        });
    }
};

document.addEventListener('DOMContentLoaded', () => {
    SM.updateShippingAddress();
    SM.updateAllThumbnails();
});
