import getCookie from "./get_cookie.js";

export default class Form {
    constructor(name, parent, form, acceptsFiles=false) {
        this.name = name;
        this.parent = parent;
        this.form = form;
        this.url = this.form.action;
        this.acceptsFiles = acceptsFiles;

        if (this.acceptsFiles) {
            this.progressBar = this.form.querySelector('.form__upload-progress');
        }

        this.form.addEventListener('submit', this.submit.bind(this));
        this.form.addEventListener('change', this.validate.bind(this));
    }

    get isValid() {
        return this.validate();
    }

    validate() {
        const inputs = new Set();
        this.form.querySelectorAll('input, select, textarea').forEach(input => {
            inputs.add(input.checkValidity());
        });
        const valid = (inputs.has(false)) ? false : true;

        return valid;
    }

    upload() {
        const name = this.name;
        const progressBar = this.progressBar;
        const form = this.form;
        const formData = new FormData(this.form);
        const csrftoken = getCookie('csrftoken');
        const request = new XMLHttpRequest();
        request.open('POST', this.url, true);
        request.setRequestHeader('x-csrf-token', csrftoken);

        // upload progress event
        request.upload.addEventListener('progress', function(e) {
            form.classList.add('uploading');
            let uploadProgress = (e.loaded / e.total) * 100;
            progressBar.value = uploadProgress;
        });

        // request finished event
        request.addEventListener('load', function(e) {
            // HTTP status message (200, 404 etc)
            if (request.status == 200) {
                form.classList.remove('uploading');
                form.reset();
                progressBar.value = 0;
                form.dispatchEvent(new CustomEvent(`contentrefresh-${name}`, {
                    bubbles: true,
                    detail: {
                        html: request.response
                    }
                }));
            } else {
                progressBar.value = 0;
                throw 'Error uploading file.';
            }
        });

        // send POST request to server
        request.send(formData);
    }

    submit(event) {
        if (event) { event.preventDefault(); }

        if (this.isValid) {
            if (this.acceptsFiles) {
                this.upload();
            } else {
                this.post();
            }
        } else {
            throw 'Form is invalid.';
        }
    }

    post(event) {
        const formData = new FormData(this.form);
        const csrftoken = getCookie('csrftoken');
        const options = {
            method: 'POST',
            body: new URLSearchParams(formData),
            mode: 'same-origin',
        };
        const request = new Request(`${this.url}`, {
            headers: { "X-CSRFToken": csrftoken },
        });

        this.fetchHTML(request, options).then(html => {
            this.form.dispatchEvent(new CustomEvent(`contentrefresh-${this.name}`, {
                bubbles: true,
                detail: {
                    html: html
                }
            }));
        });
        this.form.reset();
    }

    async fetchHTML(request, options) {
        const response = await fetch(request, options);

        if (response.ok) {
            return response.text();
        } else {
            return response.status;
        }
    }
}
