<template>
    <div class="d-inline-block">
        <label :for="inputId">
            <slot></slot>
        </label>
        <input ref="fileInput" type="file" multiple :id="inputId" @change="loadFiles" class="d-none">
    </div>
</template>

<style scoped>
</style>

<script>
import * as BIcons from "bootstrap-icons-vue";

export default {
    name: "FsFileSource",
    components: {
        ...BIcons
    },
    emits: ["input"],
    data() {
        return {
            inputId: `files-${this._uid}`
        };
    },
    methods: {
        loadFiles() {
            const files = this.$refs.fileInput?.files;
            if (!files || files.length === 0) {
                return;
            }
            const jobs = [...files].map((file) => {
                return new Promise((resolve, reject) => {
                    var reader = new FileReader();
                    reader.onload = async () => {
                        const buffer = reader.result;
                        if (!(buffer instanceof ArrayBuffer)) {
                            console.log(buffer)
                            reject("Not an ArrayBuffer");
                            return;
                        }
                        const data = new Uint8Array(buffer);
                        // SHA-256 must match the backend's content hash for file identification. See docs/implementation.md#sha-256-file-hashing-must-match-the-backend.
                        const hashBuffer = await crypto.subtle.digest('SHA-256', data);
                        const hash = Array.from(new Uint8Array(hashBuffer))
                            .map(b => b.toString(16).padStart(2, "0")).join("");
                        var base64 = btoa(
                            data.reduce((a, b) => a + String.fromCharCode(b), '')
                        );
                        resolve({
                            name: file.name,
                            size: file.size,
                            mime_type: file.type,
                            data: base64,
                            hash: hash,
                        });
                    };
                    reader.onerror = (e) => {
                        reject(e);
                    };
                    reader.readAsArrayBuffer(file)
                })
            });
            Promise.all(jobs).then((files) => {
                this.$emit("input", files)
                // Allow selecting the same file again to trigger change.
                if (this.$refs.fileInput) {
                    this.$refs.fileInput.value = '';
                }
            })
        }
    },
}
</script>