if(!app.helpers) app.helpers = {}
app.helpers.kfConsole = {

    async execCommand(event){
        if(this.outputs.commands.value.trim()=='\\help'){
            this.outputs.commands.value = ''
            this.outputs.results.innerHTML += await app.Assets.loadHtml({ name: 'help/KFconsoleHelp.html' })
            this.setupTriggers()
        } else if(this.outputs.commands.value.trim()=='\\clear'){
            this.outputs.commands.value = ''
            this.outputs.results.innerHTML = ''
        } else {
            this.outputs.results.innerHTML += await this.evalCmd(this.outputs.commands.value)
        }
        const lines = this.outputs.results.querySelectorAll('div.line')
        if(lines.length > 100) {
            for(let i=0; i<(lines.length-100); i++) lines[i].remove()
        }        
        this.outputs.results.scrollTo({ top: this.outputs.results.scrollHeight, behavior: 'smooth' })
    },

    onSnippet(evt){
        const snippetName = evt.target.dataset.snippet
        const codeDiv = this.outputs.results.querySelector(`div.snippet[data-snippet="${snippetName}"]`)
        if(codeDiv){ this.outputs.commands.value = codeDiv.textContent }
    },

    async evalCmd(code){
        const api = {
            log: (...args) => {
                const res=[]
                for(const arg of args){
                    if(typeof(arg)=='string') res.push(arg)
                    else res.push(JSON.stringify(arg))
                }
                return(res)
            },
            createAgent: async (type, properties) => {
                if(Array.from(this.outputs.agentsSelector.options).find(item => item.value==type)){
                    const defaultValues = await this.models.agents.getDefaultProps(type)
                    return(await this.newAgent(type, { ...defaultValues, ...properties })) //TODO: deepMerge
                } else {
                    throw(`Invalid agent type: ${type}`)
                }
            },
            removeAgent: async (aid) => {
                if(!Object.keys(this.kfArena.agents).includes(aid)) throw(`Agent ${aid} not on scene !`)
                this.kfArena.removeAgent(aid)
            },
            updateAgent: async (aid, properties) => {

            },
            selectAgent: async (aid) => {
                if(!Object.keys(this.kfArena.agents).includes(aid)) throw(`Agent ${aid} not on scene !`)
                this.onclickAgent(this.kfArena.scene.getObjectByName(aid))
            },
            listAgentTypes: async () => {
                return(this.agentTypes)
            },
            listAgentsOnScene: async () => {
                return(this.kfArena.agents)
            },
        }
        try {
            const fn = new Function(...Object.keys(api), `
                return(
                    (async () => { 
                        const logs = []
                        const log = (...args) => { 
                            for(const arg of args){
                                if(typeof(arg)=='string') logs.push(arg)
                                else logs.push(JSON.stringify(arg))
                            }
                        }
                        ${code}
                        return(logs)                    
                    })()
                )
            `)

            const res = await fn(...Object.values(api))
            return(
                '<div class="line">'+
                res.map(item => { 
                    if(typeof(item) == 'object') return(JSON.stringify(item))
                    return(item)
                }).join('</div><div class="line">')
                +'</div>'
            )
        } catch (err) {
            const msg = (err && err.message) ? err.message : String(err)
            return(`<div class="error">${(err && err.name) ? err.name +': ': ''}${(err && err.message) ? err.message : String(err)}</div>`)
        }
    },
}
