const SMMediaPicker = {
    upload: (files) => {
        const validFiles = Array.from(files).filter((file) => {
            return SM.mimeMatches(file.type, Alpine.store('media').require_mime_type);
        });

        if(validFiles.length === 0) {
            Alpine.store('media').error = 'No files where uploaded as they do not meet the requirements.';
        } else if(validFiles.length !== files.length) {
            Alpine.store('media').error = 'Some files where not uploaded as they do not meet the requirements.';
        } else {
            Alpine.store('media').error = null;
        }

        const titles = Array.from(validFiles).map((file) => SM.toTitleCase(file.name));

        SM.upload(validFiles, (response) => {
            if(response.files) {
                response.files.forEach((file) => {
                    SMMediaPicker.updateSelection(file.data.name);
                });
            }

            SMMediaPicker.open(
                Alpine.store('media').selected,
                {
                    require_mime_type: Alpine.store('media').require_mime_type,
                    allow_multiple: Alpine.store('media').allow_multiple,
                    allow_uploads: Alpine.store('media').allow_uploads
                },
                Alpine.store('media').callback
            );
        }, titles);
    },

    gotoLink: (url) => {
        if(url !== null) {
            const page = new URL(url).searchParams.get('page');
            SMMediaPicker.query(page, document.querySelector('input[name="search"]').value);
        }
    },

    updateSelection: (name) => {
        if (typeof name === 'string' && name !== '') {
            if (Alpine.store('media').selected.some(i => i === name)) {
                Alpine.store('media').selected = Alpine.store('media').selected.filter(i => i !== name);
            } else {
                if (!Alpine.store('media').allow_multiple) {
                    Alpine.store('media').selected = [name];
                } else {
                    Alpine.store('media').selected.push(name);
                }
            }
        }
    },

    doubleClick: (name) => {
        if (!Alpine.store('media').allow_multiple) {
            Alpine.store('media').selected = [name];
            Swal.clickConfirm();
        }
    },

    search: () => {
        SMMediaPicker.query(null, document.querySelector('input[name="search"]').value);
    },

    query: (page, search) => {
        let params = {
            mime_type: Alpine.store('media').require_mime_type,
            per_page: Alpine.store('media').per_page,
            search: search,
            'selected[]': Alpine.store('media').selected
        };

        if(page !== null) {
            params.page = page;
        }

        axios.get('/media', {
            params: params
        })
            .then(response => {
                response.data.links[0].label = '<i class="fa-solid fa-angle-left"></i>';
                response.data.links[response.data.links.length - 1].label = '<i class="fa-solid fa-angle-right"></i>';

                response.data.data.forEach((file) => {
                    file.extension = file.name.split('.').pop();
                });

                Alpine.store('media').current_page = response.data.current_page;
                Alpine.store('media').per_page = response.data.per_page;
                Alpine.store('media').to = response.data.to;
                Alpine.store('media').total = response.data.total;
                Alpine.store('media').items = response.data.data;

                Alpine.store('media').pagination = [];

                response.data.data.forEach((file) => {
                    if(file.status === 'processing') {
                        const fileName = file.name;
                        setTimeout(() => {
                            SMMediaPicker.updateThumbnail(fileName);
                        }, 5000);
                    }
                });

                Alpine.nextTick(() => {
                    Alpine.store('media').pagination = response.data.links;
                }).then(r => {
                    /* empty */
                });
            })
        .catch(error => {
                console.error(error);
            });
    },

    html: `
        <div class="flex flex-col h-full w-full" x-data="{tab: 'browser', showFileDrop: false}">
            <template x-if="$store.media.error">
                <div class="flex justify-center" role="alert">
                    <p class="relative bg-red-100 border border-red-400 text-red-700 py-2 pl-4 pr-8 text-xs rounded mb-4"><span x-text="$store.media.error"></span><i class="fa-solid fa-close text-red-900 hover:text-red-700 cursor-pointer absolute top-2 right-2" x-on:click="$store.media.error=null;"></i></p>
                </div>
            </template>
            <ul class="flex -mb-[1px] z-10">
                <li x-show="$store.media.allow_uploads" class="cursor-pointer border px-3 py-2 rounded-t-lg hover:border-t-gray-300 hover:border-x-gray-300" :class="{ 'border-gray-300': tab === 'upload', 'border-b-white': tab === 'upload', 'border-transparent': tab !== 'upload' }" x-on:click.prevent="tab='upload'">Upload</li>
                <li class="cursor-pointer border px-3 py-2 rounded-t-lg hover:border-t-gray-300 hover:border-x-gray-300" :class="{ 'border-gray-300': tab === 'browser', 'border-b-white': tab === 'browser', 'border-transparent': tab !== 'browser' }" x-on:click.prevent="tab='browser'">Browser</li>
            </ul>
            <div
                class="flex-1 border border-gray-300 overflow-y-scroll"
                x-on:dragenter.prevent="$store.media.allow_uploads ? showFileDrop = true : showFileDrop = false"
                x-on:dragover.prevent="$store.media.allow_uploads ? showFileDrop = true : showFileDrop = false">
                <div
                    id="content-upload"
                    class="w-full h-full flex flex-col px-4 py-8 justify-center items-center"
                    x-show="tab === 'upload'">
                    <h3 class="text-2xl font-bold mb-2">Drop files to upload</h3>
                    <p>or</p>
                    <label class="inline-block my-2 bg-white border border-gray-300 hover:bg-gray-300 justify-center rounded-md text-gray-700 px-8 py-1.5 text-sm font-semibold leading-6 shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 transition" for="media_upload">Select files</label>
                    <input class="hidden" id="media_upload" name="media_upload" multiple type="file" x-on:change="SMMediaPicker.upload(event.target.files)" x-bind:accept="$store.media.require_mime_type" />
                    <p class="text-xs">Maximum upload size: ${SM.bytesToString(SM.maxUploadSize())}</p>
                </div>
                <div id="content-browser" class="flex flex-col h-full w-full p-4" x-show="tab === 'browser'">
                    <form x-on:submit.prevent="SMMediaPicker.search()">
                        <div class="flex mb-2">
                            <input class="bg-white flex-grow px-2.5 py-1 text-xs text-gray-900 bg-transparent rounded-l-lg border appearance-none focus:outline-none focus:ring-0 focus:border-blue-600 peer border-gray-300 focus:ring-indigo-300" autocomplete="off" placeholder="Search" type="text" name="search" />
                            <button class="hover:bg-primary-color-dark focus-visible:outline-primary-color bg-primary-color rounded-l-none px-4 justify-center rounded-md text-white py-1.5 text-xs font-semibold leading-6 shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 transition"><i class="fa-solid fa-magnifying-glass"></i></button>
                        </div>
                    </form>

                    <ul class="flex p-2 gap-4 justify-center flex-row flex-wrap">
                    <template x-for="item in $store.media.items" :key="item.name">
                        <li
                            class="cursor-pointer flex text-center p-1 flex-items-center flex-col h-40 w-56 border-2 rounded relative"
                            :class="{'border-primary-color': $store.media.selected.some(i => i === item.name), 'border-white': !$store.media.selected.some(i => i === item.name)}"
                            x-on:click="SMMediaPicker.updateSelection(item.name)"
                            x-on:dblclick="SMMediaPicker.doubleClick(item.name)"
                            >
                            <i x-show="item.password" class="fa-solid fa-lock text-xl text-gray-600 absolute -top-2 -left-1" style="text-shadow: -1px -1px 0 #FFF, 1px -1px 0 #FFF, -1px 1px 0 #FFF, 1px 1px 0 #FFF;"></i>
                            <div x-show="$store.media.selected.some(i => i === item.name)" class="absolute -top-1.5 -right-2 w-6 h-6 bg-primary-color text-white flex items-center justify-center text-lg border border-white rounded"><i class="fa-solid fa-check"></i></div>
                            <div class="flex-grow flex items-center justify-center pointer-events-none select-none">
                                <img x-bind:src="item.thumbnail" class="rounded max-h-32" />
                            </div>
                            <div class="text-xs whitespace-nowrap overflow-hidden text-ellipsis" x-text="item.name" x-bind:title="item.name"></div>
                        </li>
                    </template>
                    </ul>

                    <div class="flex flex-1 items-end pt-4 pb-4">
                        <div class="flex w-full items-center justify-between sm:justify-center md:justify-between">
                            <p x-show="$store.media.total > 0" class="hidden md:block text-xs" x-text="'Showing ' + ((($store.media.current_page - 1) * $store.media.per_page) + 1) + ' to ' + ($store.media.current_page * $store.media.per_page > $store.media.total ? $store.media.total : $store.media.current_page * $store.media.per_page) + ' of ' + ($store.media.total) + ' results'"></p>
                            <p x-show="$store.media.total === 0" class="hidden md:block text-xs">No items found</p>

                            <ul class="hidden sm:flex border rounded-lg text-sm">
                                <template x-for="link in $store.media.pagination">
                                    <li
                                        class="px-2 py-1.5 w-9 border-r last:border-r-0 text-center select-none whitespace-nowrap"
                                        :class="{
                                            'bg-gray-100':              link.url === null,
                                            'text-gray-400':            link.url === null,
                                            'text-primary-color':       link.url !== null && link.label == $store.media.current_page,
                                            'bg-sky-100':               link.url !== null && link.label == $store.media.current_page,
                                            'cursor-pointer':           link.url !== null,
                                            'hover:text-primary-color': link.url !== null,
                                            'hover:bg-sky-100':         link.url !== null
                                            }"
                                        x-html="link.label"
                                        x-on:click="SMMediaPicker.gotoLink(link.url)"></li>
                                        </div>
                                </template>
                            </ul>

                            <a
                                :href="$store.media.pagination[0]?.url"
                                class="sm:hidden px-2 py-1.5 border rounded text-center text-sm select-none whitespace-nowrap cursor-pointer"
                                :class="{
                                    'cursor-pointer hover:text-primary-color hover:bg-sky-100': $store.media.pagination[0]?.url,
                                    'pointer-events-none text-gray-400 bg-gray-100': !$store.media.pagination[0]?.url
                                }"
                                x-on:click.prevent="SMMediaPicker.gotoLink($store.media.pagination[0].url)"
                                :disabled="!$store.media.pagination[0]?.url"
                                ><i class="fa-solid fa-angle-left mr-2"></i>Prev
                            </a>
                            <a
                                :href="$store.media.pagination[$store.media.pagination.length - 1]?.url"
                                class="sm:hidden px-2 py-1.5 border rounded text-center text-sm select-none whitespace-nowrap"
                                :class="{
                                    'cursor-pointer hover:text-primary-color hover:bg-sky-100': $store.media.pagination[$store.media.pagination.length - 1]?.url,
                                    'pointer-events-none text-gray-400 bg-gray-100': !$store.media.pagination[$store.media.pagination.length - 1]?.url
                                }"
                                x-on:click.prevent="SMMediaPicker.gotoLink($store.media.pagination[$store.media.pagination.length - 1].url)"
                                :disabled="!$store.media.pagination[$store.media.pagination.length - 1]?.url"
                                >Next<i class="fa-solid fa-angle-right ml-2"></i>
                            </a>
                        </div>
                    </div>
                </div>
            </div>
            <div
                x-show="showFileDrop"
                class="fixed flex top-0 left-0 w-full h-full z-10 bg-sky-800 bg-opacity-95 text-white items-center p-4"
                x-on:dragenter.prevent="showFileDrop = true"
                x-on:dragover.prevent="showFileDrop = true"
                x-on:drop.prevent="SMMediaPicker.upload($event.dataTransfer.files); showFileDrop = false;"
                x-on:dragleave.prevent="showFileDrop = false">
                <h2
                    class="pointer-events-none flex w-full h-full justify-center items-center text-lg font-bold border-dashed border">
                    Drop files to upload
                </h2>
            </div>
        </div>
    `,

    onOpen: () => {
        SMMediaPicker.query(null, '');
    },

    preClose: () => {
        /* empty */
    },

    open: (selected, options = {}, callback = null) => {
        if(!options.hasOwnProperty('require_mime_type')) options.require_mime_type = '*';
        if(!options.hasOwnProperty('allow_multiple')) options.allow_multiple = false;
        if(!options.hasOwnProperty('allow_uploads')) options.allow_uploads = false;

        if(selected === null || selected === '') selected = [];
        if(!Array.isArray(selected)) selected = [selected];
        Alpine.store('media').selected = selected;

        Alpine.store('media').require_mime_type = options.require_mime_type;
        Alpine.store('media').allow_multiple = options.allow_multiple;
        Alpine.store('media').allow_uploads = options.allow_uploads;
        Alpine.store('media').callback = callback;

        Swal.fire({
            title: options.allow_uploads ? 'Select or Upload Media' : 'Select Media',
            html: SMMediaPicker.html,
            confirmButtonText: 'Select',
            confirmButtonColor: '#0284C7',
            cancelButtonText: 'Cancel',
            showCancelButton: true,
            focusConfirm: false,
            reverseButtons: true,
            didOpen: SMMediaPicker.onOpen,
            preConfirm: SMMediaPicker.preClose,
            customClass: {
                container: 'sm-media-picker-container',
                popup: 'sm-media-picker',
            }
        }).then((result) => {
            if(result.isConfirmed && callback) {
                if(Alpine.store('media').allow_multiple) {
                    callback(Alpine.store('media').selected);
                } else {
                    if(Alpine.store('media').selected.length > 0) {
                        callback(Alpine.store('media').selected[0]);
                    } else {
                        callback('');
                    }
                }
            }
        })
    },

    updateThumbnail: (name) => {
        axios.get('/media/' + name)
            .then(response => {
                const item = Alpine.store('media').items.find(i => i.name === name);
                if(item) {
                    if(response.data.status === 'ready') {
                        item.thumbnail = response.data.thumbnail;
                        item.status = response.data.status;
                        item.variants = response.data.variants;
                    } else if(response.data.status === 'processing') {
                        setTimeout(() => {
                            SMMediaPicker.updateThumbnail(name);
                        }, 5000);
                    }
                }
            })
            .catch(error => {
                console.error(error);
            });
    }
};

window.SMMediaPicker = SMMediaPicker;

document.addEventListener('DOMContentLoaded', () => {
    Alpine.store('media', {
        require_mime_type: '*',
        allow_multiple: true,
        allow_uploads: false,
        current_page: 1,
        per_page: 24,
        to: 0,
        total: 0,
        items: [],
        selected: [],
        pagination: [],
    });
})

