<script lang="ts">
interface Props {
    log_lvl?: number;
    // Expecting these for link_to_type: 'event', 'event_location', 'event_presentation', 'event_presenter', 'event_session'
    link_to_type: string;
    link_to_id: string;
    input_name?: string;
    multiple?: boolean;
    required?: boolean;
    accept?: string;
    class_li_default?: string;
    class_li?: string;
    input_class_li?: string[];
    table_class_li?: string[];
    upload_complete?: boolean;
    submit_status?: null|string;
    label?: import('svelte').Snippet;
}

let {
    log_lvl = $bindable(0),
    link_to_type,
    link_to_id,
    input_name = 'file_list',
    multiple = true,
    required = true,
    accept = 'audio/*, image/*, video/*, .bak, .cfg, .css, .csv, .doc, .docx, .gz, .htm, .html, .ini, .iso, .j2, .json, .key, .keynote, .md, .pdf, .ppt, .pptx, .rar, .rtf, .sql, .svelte, ttf, .txt, .xls, .xlsx, .xz, .zip, .bin, .dmg, .exe, .js, .msi, .php, .py, .sh',
    class_li_default = 'flex flex-col gap-1 items-center justify-center w-full max-w-2xl mx-auto my-1',
    class_li = '',
    input_class_li = ['file_drop_area'],
    table_class_li = ['table', 'table-sm', 'table-striped', '' , 'text-sm'],
    upload_complete = $bindable(false),
    submit_status = $bindable(null),
    label
}: Props = $props();

// Imports
// Import components and elements
import Element_input_files_tbl from '$lib/element_input_files_tbl.svelte';

// Import storage, functions, and libraries
import type { key_val } from '$lib/ae_stores';

import { api } from '$lib/api';
import { ae_snip, ae_loc, ae_sess, ae_api, ae_trig, slct, slct_trigger } from '$lib/ae_stores';
import { events_loc, events_sess, events_slct, events_trigger } from '$lib/ae_events_stores';
import { events_func } from '$lib/ae_events_functions';
import { db_events } from "$lib/ae_events/db_events";

// Exports

// Local Variables
let task_id = $state(link_to_id);
let input_file_list: any = $state(null);
let ae_promises: key_val = $state({}); // Promise<any>;
let ae_triggers: key_val = {};

let input_element_id = 'ae_comp__event_files_upload__input';


// *** Functions and Logic
function preventDefault(fn) {
    return function (event) {
        event.preventDefault();
        fn.call(this, event);
    };
}

async function handle_submit_form_files(event) {
    console.log('*** handle_submit_form() ***');

    $events_sess.files.disable_submit__event_file_obj = true;
    $events_sess.files.submit_status = 'saving';
    submit_status = 'saving';
    upload_complete = false;

    let hosted_file_results;

    if (event.target[input_element_id].files.length > 0) {
        task_id = link_to_id; // Ideally this should be the file hash, but we may be uploading multiple files at once. This should be done with a loop instead?

        // Loop through each file and upload them individually in event.target[input_element_id].files
        // The task_id should be the file hash.
        // processed_file_list[i] has the file hash_sha256, hash_sha256_match, warnings, uploaded, uploaded_bytes, filename, and file_size_bytes.
        for (let i = 0; i < event.target[input_element_id].files.length; i++) {
            let tmp_file = event.target[input_element_id].files[i];

            task_id = $events_sess.files.processed_file_list[i].hash_sha256;

            hosted_file_results = await handle_input_upload_files([tmp_file], task_id);

            if (hosted_file_results) {
                console.log(`hosted_file_results:`, hosted_file_results);
            } else {
                console.log(`hosted_file_results:`, hosted_file_results);
            }
        }
        // hosted_file_results = await handle_input_upload_files(event.target[input_element_id].files, task_id);
        $events_sess.files.processed_file_list = [];
        $events_sess = $events_sess;
        event.target.reset();
        // await tick();


        db_events.files.clear();

        events_func.load_ae_obj_li__event_file({
            api_cfg: $ae_api,
            for_obj_type: link_to_type,
            for_obj_id: link_to_id,
            enabled: 'all',
            hidden: 'all',
            try_cache: true
        });
    }

    $events_sess.files.disable_submit__event_file_obj = false;
    $events_sess.files.submit_status = 'saved';
    submit_status = 'saved';
    upload_complete = true;
}


async function handle_input_upload_files(input_upload_files, task_id) {
    log_lvl = 0;
    if (log_lvl) {
        console.log(`*** handle_input_upload_files() *** task_id = ${task_id}`);
    }

    const form_data = new FormData();

    form_data.append('account_id', $ae_loc.account_id);
    form_data.append('link_to_type', link_to_type);
    form_data.append('link_to_id', link_to_id);

    for (let i = 0; i < input_upload_files.length; i++) {
        form_data.append(`file_list`, input_upload_files[i]);
    }

    // hash_sha256, uploaded, uploaded_bytes
    // $events_sess.files.processed_file_list[i] = {
    //     ...$events_sess.files.processed_file_list[i],
    //     uploaded: $ae_sess.api_upload_kv[link_to_id].percent_completed,
    //     uploaded_bytes: $ae_sess.api_upload_kv[link_to_id].uploaded_bytes,
    // };

    let params = null;

    let endpoint = '/hosted_file/upload_files';

    // console.log(form_data);

    params = null;

    // Uncomment and the post_promise is not seen by the "await" below
    // post_promise = await api.post_object({api_cfg: $cfg.api, endpoint: endpoint, params: params, data:form_data});
    // Uncomment so that the post_promise is not seen by the "await" below
    ae_promises.upload__hosted_file_obj = api.post_object({
        api_cfg: $ae_api,
        endpoint: endpoint,
        // params: params,
        form_data: form_data,
        task_id: task_id,
        log_lvl: log_lvl,
        // retry_count: 1,
    })
    .then(async function (result) {
        // console.log('HERE!!', result);

        // WARNING!!!! ONLY ONE FILE IS EXPECTED TO BE UPLOADED AT A TIME!!!
        // NOTE: The /hosted_file/upload_files endpoint will always return a list of successful files uploaded. In this case we are only uploading one file and expecting a list of one item.
        let x = 0;
        if (log_lvl) {
            console.log(`result = `, result[x]);
        }
        let hosted_file_obj = result[x];

        let hosted_file_id = hosted_file_obj.hosted_file_id_random;

        let event_file_data: key_val = {};
        event_file_data['hosted_file_id_random'] = hosted_file_id;
        event_file_data['for_type'] = link_to_type;
        event_file_data['for_id_random'] = link_to_id;
        event_file_data['filename'] = hosted_file_obj.filename;
        event_file_data['extension'] = hosted_file_obj.extension;
        event_file_data['enable'] = true;
        if (log_lvl) {
            console.log(`event_file_data = `, event_file_data);
        }

        // $events_sess.files.new_upload_list[i].uploaded_bytes = 10; // fake 10 bytes at least...

        let event_file_id = await events_func.create_event_file_obj_from_hosted_file_async({
            api_cfg: $ae_api,
            hosted_file_id: hosted_file_id,
            data: event_file_data,
            log_lvl: log_lvl
            })
        .then(function (create_result) {
            console.log(create_result); // NOTE: This should be the event_file_id string
            // let event_file_id = create_result;
            return create_result;
        });

        return event_file_id;
    })
    .then(function (event_file_id) {
        // NOTE: Need to make sure the event file records are created first. The update won't see the changes if too fast.
        // dispatch(
        //     'event_file_obj_li_updated',
        //     {
        //         link_to_type: link_to_type,
        //         link_to_id: link_to_id,
        //     }
        // );

        // $ae_events.pres_mgmt.new_upload_list[i].uploaded = true;
        // $ae_events.pres_mgmt.new_upload_list[i].uploaded_bytes = event.target.event_file_upload_file_list.files[i].size;

        return event_file_id;
    })
    .catch(function (error) {
        console.log('Something went wrong.');
        console.log(error);
        return false;
    })
    .finally( function () {
        // $events_sess.files.files_uploading_count--;
        $slct_trigger = 'load__event_file_obj_li';

        // return event_file_id;
    });

    console.log(ae_promises.upload__hosted_file_obj);
    let hosted_file_result = ae_promises.upload__hosted_file_obj;

    return hosted_file_result;
}

</script>


<!-- class:hidden={!$ae_loc.trusted_access} -->
<form
    onsubmit={preventDefault(handle_submit_form_files)}
    class="{class_li_default} {class_li}"
    >

    {#await ae_promises.upload__hosted_file_obj}
    <div class="text-lg flex flex-row gap-1 items-center justify-center">
        <span class="fas fa-spinner fa-spin m-1"></span>
        <span class="">
            Uploading
            {#if $ae_sess.api_upload_kv[task_id]}
                {$ae_sess.api_upload_kv[task_id].percent_completed}%
            {/if}
        </span>
    </div>
    {/await}

    <div
        class="
            border-2 hover:border-2 border-dashed border-green-500
            p-1
            preset-filled-success-50-950 hover:border-green-800
            cursor-pointer
            "
        >
    <label
        for="ae_comp__event_files_upload__input"
        class="
            svelte_input_file_label
            text-center
            cursor-pointer
            "
        class:hidden={$events_sess.files.disable_submit__event_file_obj}
        >
        {#if label}{@render label()}{:else}
        <div class="text-lg">
            <span class="fas fa-upload"></span>
            <!-- Select files to upload -->
            <!-- <span class="fas fa-file-archive"></span> -->
            <strong class="">Upload files</strong>
            <!-- (drag and drop) -->
        </div>
        <div class="text-sm text-gray-600 dark:text-gray-400 italic">
            <strong>Presentation related files only</strong><br>
            (PowerPoint, Keynote, PDF, mp4, Word Doc, Excel, txt, etc)
        </div>
        {/if}
    </label>

    <input
        id={input_element_id}
        type="file"
        bind:files={input_file_list}
        {multiple}
        {required}
        {accept}
        name={input_name}
        class:hidden={$events_sess.files.disable_submit__event_file_obj}
        class="
            svelte_input_file_element file-dropzone-input
            block w-full text-lg text-center
            rounded-lg
            cursor-pointer
            p-1
            preset-tonal-primary preset-outlined-primary-200-800 hover:preset-filled-success-200-800
            transition-all
            {input_class_li.join(' ')}
            "
        />
    </div>

    <Element_input_files_tbl
        bind:input_file_list={input_file_list}

        bind:file_list_status={$events_sess.files.status__file_list}
        bind:processed_file_list={$events_sess.files.processed_file_list}
        table_class_li={table_class_li}
        />

    <button
        type="submit"
        class="
            btn btn-lg
            text-lg
            preset-tonal-primary hover:preset-tonal-success
            flex items-center justify-center
            w-54
            transition-all
            "
        class:opacity-20={$events_sess.files.disable_submit__event_file_obj || $events_sess.files.status__file_list != 'ready'}
        disabled={$events_sess.files.disable_submit__event_file_obj || $events_sess.files.status__file_list != 'ready'}
        >
        {#await ae_promises.upload__hosted_file_obj}
            <span class="fas fa-spinner fa-spin m-1"></span>
            <span class="">
                Uploading
                {#if $ae_sess.api_upload_kv[task_id]}
                    {$ae_sess.api_upload_kv[task_id].percent_completed}%
                {/if}
            </span>
        {:then}
            <span class="fas fa-upload m-1"></span>
            <span class="">
                Upload
            </span>
            <!-- <span class="fas fa-save m-1"></span> -->
            <span class="text-sm px-1 font-semibold bg-neutral-500/50 rounded">
                {#if $events_sess.files.processed_file_list.length > 0}
                    <!-- {#each $events_sess.files.processed_file_list as file_obj, index}
                        <span class="text-xs">
                            {file_obj.filename}
                        </span>
                    {/each} -->
                    {@html $events_sess.files.processed_file_list.length == 1 ? `${$events_sess.files.processed_file_list.length}&times; file` : `${$events_sess.files.processed_file_list.length}&times; files`}
                {:else}
                    <span class="text-xs">
                        No files selected
                    </span>
                {/if}
                <!-- Files -->
            </span>
        {/await}
    </button>
</form>
