import { createApp } from './vue.esm-browser.js';

import Cluster from './Cluster.js';
import Host    from './Host.js';

createApp({
    components: { Cluster, Host },
    data() {
        return {
            forms: {
                store: {  },
            },
            session: {},
            error: null,
            publicState: null,
            uiHash: null,
            watchingState: false,
            state: null,
        }
    },
    mounted() {
        this.session = JSON.parse(sessionStorage.state || "{}")
        this.watchPublicState()
    },
    watch: {
        session: {
            deep: true,
            handler(v) {
                sessionStorage.state = JSON.stringify(v)

                if (v.token && !this.watchingState) {
                    this.watchState()
                    this.watchingState = true
                }
            }
        },
        publicState: {
            deep: true,
            handler(v) {
                if (v) {
                    if (this.uiHash && v.UIHash != this.uiHash) {
                        console.log("reloading")
                        location.reload()
                    } else {
                        this.uiHash = v.UIHash
                    }
                }
            },
        }
    },

    methods: {
        copyText(text) {
            event.preventDefault()
            window.navigator.clipboard.writeText(text)
        },
        setToken() {
            event.preventDefault()
            this.session.token = this.forms.setToken
            this.forms.setToken = null
        },
        storeAddKey() {
            this.apiPost('/store/add-key', this.forms.store.pass1, (v) => {
                this.forms.store = {}
            })
        },
        unlockStore() {
            this.apiPost('/public/unlock-store', this.forms.store.pass1, (v) => {
                this.forms.store = {}

                if (v) {
                    this.session.token = v
                    if (!this.watchingState) {
                        this.watchState()
                        this.watchingState = true
                    }
                }
            })
        },
        apiPost(action, data, onload) {
            event.preventDefault()

            if (data === undefined) {
                throw("action " + action + ": no data")
            }

            /* TODO
            fetch(action, {
                method: 'POST',
                body: JSON.stringify(data),
            })
              .then((response) => response.json())
              .then((result) => onload)
            // */

            var xhr = new XMLHttpRequest()

            xhr.responseType = 'json'
            // TODO spinner, pending aciton notification, or something
            xhr.onerror = () => {
                // this.actionResults.splice(idx, 1, {...item, done: true, failed: true })
            }
            xhr.onload = (r) => {
                if (xhr.status != 200) {
                    this.error = xhr.response
                    return
                }
                // this.actionResults.splice(idx, 1, {...item, done: true, resp: xhr.responseText})
                this.error = null
                if (onload) {
                    onload(xhr.response)
                }
            }

            xhr.open("POST", action)
            xhr.setRequestHeader('Accept', 'application/json')
            xhr.setRequestHeader('Content-Type', 'application/json')
            if (this.session.token) {
                xhr.setRequestHeader('Authorization', 'Bearer '+this.session.token)
            }
            xhr.send(JSON.stringify(data))
        },
        download(url) {
            event.target.target = '_blank'
            event.target.href = this.downloadLink(url)
        },
        downloadLink(url) {
            // TODO once-shot download link
            return url + '?token=' + this.session.token
        },
        watchPublicState() {
            this.watchStream('publicState', '/public-state')
        },
        watchState() {
            this.watchStream('state', '/state', true)
        },
        watchStream(field, path, withToken) {
            let evtSrc = new EventSource(path + (withToken ? '?token='+this.session.token : ''));
            evtSrc.onmessage = (e) => {
                let update = JSON.parse(e.data)

                console.log("watch "+path+":", update)

                if (update.err) {
                    console.log("watch error from server:", err)
                }
                if (update.set) {
                    this[field] = update.set
                }
                if (update.p) { // patch
                    new jsonpatch.JSONPatch(update.p, true).apply(this[field])
                }
            }
            evtSrc.onerror = (e) => {
                // console.log("event source " + path + " error:", e)
                if (evtSrc) evtSrc.close()

                this[field] = null

                window.setTimeout(() => { this.watchStream(field, path, withToken) }, 1000)
            }
        },
    }

}).mount('#app')