{{ template "base.html" . }}

{{ define "extrahead" }}
    {{ template "markdown_previews.html" . }}

    <script src="{{ static "js/base64.js" }}"></script>

    <style>
        #editor {
            resize: vertical;
        }

        #editor.drop {
            box-shadow: inset 0px 0px 5px yellow;
        }
    </style>
{{ end }}

{{ define "content" }}
<div class="content-block ph3 ph0-ns">
    {{ if not .CanEditTitle }}
        <h2>{{ .Title }}</h2>
    {{ end }}
    <div class="flex flex-column flex-row-ns">
        <form id="form" action="{{ .SubmitUrl }}" method="post" class="flex-fair-ns overflow-hidden">
            {{ csrftoken .Session }}

            {{ if .CanEditTitle }}
                <input id="title" class="b w-100 mb1" name="title" type="text" placeholder="Post title..." value="{{ .Title }}" />
            {{ end }}
            {{/* TODO: Reintroduce the toolbar in a way that makes sense for Markdown */}}
            {{/*
            <div class="toolbar" id="toolbar">
                <input type="button" id="bold" value="B" />
                <input type="button" id="italic" value="I" /> 
                <input type="button" id="underline" value="U" /> 
                <input type="button" id="monospace" value="monospace" /> 
                <input type="button" id="url" value="url" /> 
                <input type="button" id="img" value="img" /> 
                <input type="button" id="code" value="code" /> 
                <input type="button" id="quote_simple" value="quote (anon)" /> 
                <input type="button" id="quote_member" value="quote (member)" /> 
                <input type="button" id="spoiler" value="spoiler" /> 
                <input type="button" id="lalign" value="Left" /> 
                <input type="button" id="calign" value="Center" /> 
                <input type="button" id="ralign" value="Right" />
                <input type="button" id="ulist" value="ul" />
                <input type="button" id="olist" value="ol" />
                <input type="button" id="litem" value="li" />
                <input type="button" id="youtube" value="youtube" />
            </div>
            */}}
            <textarea id="editor" class="w-100 h6 minh-6 pa2 mono lh-copy" name="body">{{ .EditInitialContents }}</textarea>

            <div class="flex justify-end items-center mt2">
                <div class="upload_bar flex-grow-1">
                    <div class="instructions">
                        Upload files by dragging & dropping, pasting, or <label class="pointer link" for="file_input">selecting</label> them.
                    </div>
                    <div class="progress flex">
                        <div class="progress_text mr3"></div>
                        <div class="progress_bar flex-grow-1 flex-shrink-1 pa1"><div class=""></div></div>
                    </div>
                </div>
                <input type="submit" class="button ml2 flex-grow-0 flex-shrink-0" name="submit" value="{{ .SubmitLabel }}" />
            </div>

            {{ if .IsEditing }}
                <span class="editreason">
                    <label for="editreason">Edit reason:</label>
                    <input name="editreason" maxlength="255" type="text" id="editreason" />
                </span>
            {{ end }}

            {{ with .PostReplyingTo }}
                <h4 class="mt3">The post you're replying to:</h4>
                <div class="mh-6 overflow-y-auto">
                    {{ template "forum_post_standalone.html" . }}
                </div>
            {{ end }}
        </form>
        <div id="preview-container" class="post post-preview mathjax flex-fair-ns overflow-auto mv3 mv0-ns ml3-ns pa3 br3 bg--dim">
            <div id="preview" class="post-content"></div>
        </div>
        <input type="file" multiple name="file_input" id="file_input" class="dn" />{{/* NOTE(asaf): Placing this outside the form to avoid submitting it to the server by accident */}}
    </div>
</div>

<script>
    const maxFileSize = {{ .MaxFileSize }};
    const uploadUrl = {{ .UploadUrl }};

    const form = document.querySelector('#form');
    const titleField = document.querySelector('#title'); // may be undefined, be careful!
    const textField = document.querySelector('#editor');
    const preview = document.querySelector('#preview');

    // Save content on change, clear on submit
    const clearFuncs = [];
    if (titleField) {
        const { clear: clearTitle } = autosaveContent({
            inputEl: titleField,
            storageKey: `post-title/${window.location.host}${window.location.pathname}`,
        });
        clearFuncs.push(clearTitle);
    }
    const { clear: clearContent } = autosaveContent({
        inputEl: textField,
        storageKey: `post-content/${window.location.host}${window.location.pathname}`,
    });
    clearFuncs.push(clearContent);
    form.addEventListener('submit', e => {
        for (const clear of clearFuncs) {
            clear();
        }
    });

    // Do live Markdown previews
    let doMarkdown = initLiveMarkdown({ inputEl: textField, previewEl: preview });

    /*
    / Asset upload
    */ 
    const submitButton = document.querySelector("#form input[type=submit]");
    const submitText = submitButton.value;
    const fileInput = document.querySelector('#file_input');
    const uploadBar = document.querySelector('.upload_bar');
    const uploadProgress = document.querySelector('.upload_bar .progress');
    const uploadProgressText = document.querySelector('.upload_bar .progress_text');
    const uploadProgressBar = document.querySelector('.upload_bar .progress_bar');
    const uploadProgressBarFill = document.querySelector('.upload_bar .progress_bar > div');
    let fileCounter = 0;
    let enterCounter = 0;
    let uploadQueue = [];
    let currentUpload = null;
    let currentXhr = null;
    let currentBatchSize = 0;
    let currentBatchDone = 0;

    fileInput.addEventListener("change", function(ev) {
        if (fileInput.files.length > 0) {
            importUserFiles(fileInput.files);
        }
    });

    textField.addEventListener("dragover", function(ev) {
        let effect = "none";
        for (let i = 0; i < ev.dataTransfer.items.length; ++i) {
            if (ev.dataTransfer.items[i].kind.toLowerCase() == "file") {
                effect = "copy";
                break;
            }
        }
        ev.dataTransfer.dropEffect = effect;
        ev.preventDefault();
    });

    textField.addEventListener("dragenter", function(ev) {
        enterCounter++;
        let droppable = false;
        for (let i = 0; i < ev.dataTransfer.items.length; ++i) {
            if (ev.dataTransfer.items[i].kind.toLowerCase() == "file") {
                droppable = true;
                break;
            }
        }
        if (droppable) {
            textField.classList.add("drop");
        }
    });

    textField.addEventListener("dragleave", function(ev) {
        enterCounter--;
        if (enterCounter == 0) {
            textField.classList.remove("drop");
        }
    });

    function makeUploadString(uploadNumber, filename) {
        return `Uploading file #${uploadNumber}: \`${filename}\`...`;
    }

    textField.addEventListener("drop", function(ev) {
        enterCounter = 0;
        textField.classList.remove("drop");

        if (ev.dataTransfer && ev.dataTransfer.files) {
            importUserFiles(ev.dataTransfer.files)
        }

        ev.preventDefault();
    });

    textField.addEventListener("paste", function(ev) {
        const files = ev.clipboardData?.files ?? [];
        if (files.length > 0) {
            importUserFiles(files)
        }
    });

    function importUserFiles(files) {
        let items = [];
        for (let i = 0; i < files.length; ++i) {
            let f = files[i];
            if (f.size < maxFileSize) {
                items.push({ file: f, error: null });
            } else {
                items.push({ file: null, error: `\`${f.name}\` is too big! Max size is ${maxFileSize} but the file is ${f.size}.` });
            }
        }

        let cursorStart = textField.selectionStart;
        let cursorEnd = textField.selectionEnd;

        let toInsert = "";
        let linesToCursor = textField.value.substr(0, cursorStart).split("\n");
        let cursorLine = linesToCursor[linesToCursor.length-1].trim();
        if (cursorLine.length > 0) {
            toInsert = "\n\n";
        }
        for (let i = 0; i < items.length; ++i) {
            if (items[i].file) {
                fileCounter++;
                toInsert += makeUploadString(fileCounter, items[i].file.name) + "\n\n";
                queueUpload(fileCounter, items[i].file);
            } else {
                toInsert += `${items[i].error}\n\n`;
            }
        }

        textField.value = textField.value.substring(0, cursorStart) + toInsert + textField.value.substring(cursorEnd, textField.value.length);
        doMarkdown();
        uploadNext();
    }

    function replaceUploadString(upload, newString) {
        let cursorStart = textField.selectionStart;
        let cursorEnd = textField.selectionEnd;
        let uploadString = makeUploadString(upload.uploadNumber, upload.file.name);
        let insertIndex = textField.value.indexOf(uploadString)
        textField.value = textField.value.replace(uploadString, newString);
        if (cursorStart <= insertIndex + uploadString.length) {
            textField.selectionStart = cursorStart;
        } else {
            textField.selectionStart = cursorStart - uploadString.length + newString.length;
        }
        if (cursorEnd <= insertIndex + uploadString.length) {
            textField.selectionEnd = cursorEnd;
        } else {
            textField.selectionEnd = cursorEnd - uploadString.length + newString.length;
        }
        doMarkdown();
    }

    function replaceUploadStringError(upload) {
        replaceUploadString(upload, `There was a problem uploading your file \`${upload.file.name}\`.`);
    }

    function queueUpload(uploadNumber, file) {
        uploadQueue.push({
            uploadNumber: uploadNumber,
            file: file
        });

        currentBatchSize++;
        uploadProgressText.textContent = `Uploading files ${currentBatchDone+1}/${currentBatchSize}`;
    }

    function uploadDone(ev) {
        try {
            if (currentXhr.status == 200 && currentXhr.response) {
                if (currentXhr.response.url) {
                    let url = currentXhr.response.url;
                    let newString = `[${currentUpload.file.name}](${url})`;
                    if (currentXhr.response.mime.startsWith("image")) {
                        newString = "!" + newString;
                    }

                    replaceUploadString(currentUpload, newString);
                } else if (currentXhr.response.error) {
                    replaceUploadString(currentUpload, `Upload failed for \`${currentUpload.file.name}\`: ${currentXhr.response.error}.`);
                } else {
                    replaceUploadStringError(currentUpload);
                }
            } else {
                replaceUploadStringError(currentUpload);
            }
        } catch (err) {
            console.error(err);
            replaceUploadStringError(currentUpload);
        }
        currentUpload = null;
        currentXhr = null;
        currentBatchDone++;
        uploadNext();
    }

    function updateUploadProgress(ev) {
        if (ev.lengthComputable) {
            let progress = ev.loaded / ev.total;
            uploadProgressBarFill.style.width = Math.floor(progress * 100) + "%";
        }
    }

    function uploadNext() {
        if (currentUpload == null) {
            next = uploadQueue.shift();
            if (next) {
                uploadProgressText.textContent = `Uploading files ${currentBatchDone+1}/${currentBatchSize}`;
                uploadBar.classList.add("uploading");
                uploadProgressBarFill.style.width = "0%";
                submitButton.disabled = true;
                submitButton.value = "Uploading files...";

                try {
                    let utf8Filename = strToUTF8Arr(next.file.name);
                    let base64Filename = base64EncArr(utf8Filename);
                    // NOTE(asaf): We use XHR because fetch can't do upload progress reports. Womp womp. https://youtu.be/Pubd-spHN-0?t=2
                    currentXhr = new XMLHttpRequest();
                    currentXhr.upload.addEventListener("progress", updateUploadProgress);
                    currentXhr.open("POST", uploadUrl, true);
                    currentXhr.setRequestHeader("Hmn-Upload-Filename", base64Filename);
                    currentXhr.responseType = "json";
                    currentXhr.addEventListener("loadend", uploadDone);
                    currentXhr.send(next.file);
                    currentUpload = next;
                } catch (err) {
                    replaceUploadStringError(next);
                    console.error(err);
                    uploadNext();
                }
            } else {
                submitButton.disabled = false;
                submitButton.value = submitText;
                uploadBar.classList.remove("uploading");
                currentBatchSize = 0;
                currentBatchDone = 0;
            }
        }
    }
</script>
{{ end }}
