<template>
    <div ref="list" class="a-select-file-list">
        <form ref="form" class="flex-column" v-if="state == STATE.DEFAULT">
            <slot name="form"></slot>
            <div class="field is-horizontal">
                <label class="label">{{ label }}</label>
                <input type="file" ref="uploadFile" :name="fieldName" @change="onFileChange"/>
            </div>
            <div class="flex-row align-right" v-if="submitLabel">
                <button type="button" class="button small" @click="submit">
                    {{ submitLabel }}
                </button>
            </div>
        </form>
        <div class="flex-column" v-else>
            <slot name="preview" :fileUrl="fileUrl" :file="file" :loaded="loaded" :total="total"></slot>
            <div class="flex-row">
                <progress :max="total" :value="loaded"/>
                <button type="button" class="button small square ml-2" @click="abort">
                    <span class="icon small">
                        <i class="fa fa-close"></i>
                    </span>
                </button>
            </div>
        </div>
    </div>
</template>
<script>
import {getCsrf} from "../model.js"

export default {
    emit: ["fileChange", "load", "abort", "error"],

    props: {
        url: { type: String },
        fieldName: { type: String, default: "file" },
        label: { type: String, default: "Select a file" },
        submitLabel: { type: String, default: "Upload" },
    },

    data() {
        return {
            STATE: {
                DEFAULT: 0,
                UPLOADING: 1,
            },
            state: 0,
            upload: {},
            file: null,
            fileUrl: null,
            total: 0,
            loaded: 0,
            request: null,
        }
    },

    methods: {
        abort() {
            this.request && this.request.abort()
        },

        onFileChange() {
            const [file] = this.$refs.uploadFile.files
            if(!file)
                return
            this._setUploadFile(file)
            this.$emit("fileChange", {upload: this, file: this.file, fileUrl: this.fileUrl})
        },

        submit() {
            const req = new XMLHttpRequest()
            req.open("POST", this.url)
            req.upload.addEventListener("progress", (e) => this.onUploadProgress(e))
            req.addEventListener("load", (e) => this.onUploadDone(e, 'load'))
            req.addEventListener("abort", (e) => this.onUploadDone(e, 'abort'))
            req.addEventListener("error", (e) => this.onUploadDone(e, 'error'))

            const formData = new FormData(this.$refs.form);
            formData.append('csrfmiddlewaretoken', getCsrf())
            req.send(formData)

            this._resetUpload(this.STATE.UPLOADING, false, req)
        },

        onUploadProgress(event) {
            this.loaded = event.loaded
            this.total = event.total
        },

        onUploadDone(event, eventName) {
            this.$emit(eventName, event)
            this._resetUpload(this.STATE.DEFAULT, true)
        },

        _setUploadFile(file) {
            this.file = file
            this.fileURL = file && URL.createObjectURL(file)
        },

        _resetUpload(state, resetFile=false, request=null) {
            this.state = state
            this.loaded = 0
            this.total = 0
            this.request = request
            if(resetFile)
                this.file = null
        }

    },}
</script>
