<template>
    <div class="row parentContainer">
        <div class="col">
            <div class="requestModal pointer h-100" @click="loadFile" data-type="filePreview">
                <slot name="button"></slot>
            </div>
            <modal-component styleType="fill-in" size="extra-large" type="filePreview">
                <loading-component style="height: 200px; top: 0;" key="1" color="success" v-show="isLoading"></loading-component>
                <div class="row">
                    <div class="col text-center">
                        <img :src="src" class="w-100" v-if="type !== 'pdf'">
                        <div class="btn btn-info b-rad-none pointer m-b-20" @click="openBase64NewTab" v-show="type === 'pdf'">Open in new window</div>
                        <a :href="'data:application/pdf;base64,' + src" :download="file.file.filename" v-show="type === 'pdf'"><div class="btn btn-success b-rad-none pointer m-b-20">Download</div></a>
                        <iframe v-if="type === 'pdf' && isClicked" class="pdf-display w-100 scrollable" style="height: 80vh" :src="'data:application/pdf;base64,' + src"></iframe>
                    </div>
                </div>
            </modal-component>
        </div>
    </div>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import route from '@/general/functions/router';
import { useRequest } from '@/composables/useRequest';

const props = defineProps<{
    file: Record<string, any>;
}>();

const { submit } = useRequest();

const isLoading = ref(false);
const loaded = ref(false);
const src = ref('');
const isClicked = ref(false);

watch(
    () => props.file,
    () => {
        loaded.value = false;
        src.value = '';
        isClicked.value = false;
    }
);

const type = computed(() => {
    return props.file.file.mime_type === 'application/pdf' ? 'pdf' : 'image';
});

const asset = (path: string) => (window as any).Vapor.asset(path);

const renderPdf = () => {
    isLoading.value = false;
};

const base64toBlob = (base64Data: string) => {
    const sliceSize = 1024;
    const byteCharacters = atob(base64Data);
    const bytesLength = byteCharacters.length;
    const slicesCount = Math.ceil(bytesLength / sliceSize);
    const byteArrays = new Array(slicesCount);

    for (let sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
        const begin = sliceIndex * sliceSize;
        const end = Math.min(begin + sliceSize, bytesLength);

        const bytes = new Array(end - begin);
        for (let offset = begin, i = 0; offset < end; ++i, ++offset) {
            bytes[i] = byteCharacters[offset].charCodeAt(0);
        }
        byteArrays[sliceIndex] = new Uint8Array(bytes);
    }

    return new Blob(byteArrays, { type: 'application/pdf' });
};

const openBase64NewTab = () => {
    const blob = base64toBlob(src.value);
    if (window.navigator && (window.navigator as any).msSaveOrOpenBlob) {
        (window.navigator as any).msSaveOrOpenBlob(blob, 'pdfBase64.pdf');
        return;
    }

    const blobUrl = URL.createObjectURL(blob);
    window.open(blobUrl);
};

const loadFile = async () => {
    isClicked.value = true;
    if (loaded.value) {
        return;
    }

    isLoading.value = true;
    const filePath = type.value === 'pdf'
        ? props.file.file.file_info.original.file
        : props.file.file.file_info[0].original.file;

    await submit(
        `${route('api.storage.document.file', filePath)}/`,
        'get',
        'imagePreviewSection',
        false,
        false,
        undefined,
        {
            successHandler: (response) => {
                loaded.value = true;
                src.value = response.payload.src;
                isLoading.value = false;

                if (type.value === 'pdf') {
                    renderPdf();
                }
            },
            errorHandler: (_response, statusCode) => {
                src.value = statusCode === 404 ? asset('images/3231370.jpg') : asset('images/2942005.jpg');
                isLoading.value = false;
            }
        }
    );
};
</script>

<style scoped>

</style>
