class KeyframeView extends WindozDomContent {

    constructor() {
        super()
        Object.assign(this, app.helpers.activeAttributes, app.helpers.formBuilder, app.helpers.kfConsole)
    }
    
    DOMContentFocused(options) { 
        if(this.wasBlured){ // Avoid 2nd refesh on DomContentLoaded
            //this.refreshyoustuff() 
        }
        this.wasBlured = false
    }

    DOMContentBlured(options) { this.wasBlured = true }

    async DOMContentLoaded(options) {    
        this.windowPrefsId = `editors.keyframeview`
        this.models = options.models
        const components = ui.eicfy(this.el)       
        this.setupTriggers(components)        
        this.setupRefs(components)

        const [sprites, types] = await Promise.all([
            this.models.agents.getSprites('Basic 3D'),
            this.models.agents.getTypes('Test agents')
        ])

        this.agentSprites = sprites
        this.agentTypes = types
        this.currentAgentType = null

        //TODO from browser
        this.currentKeyframe = { }

        this.outputs.agentsSelector.fillOptions( this.agentTypes.map(item => {
            return({ markup: `<i class="icon-${item.atp_hascode ? 'bug' : 'atom1'}"></i>${item.atp_name}`, value: item.atp_id})
        }))
        this.outputs.agentsSelector.addEventListener('change',this.onChangeAgent.bind(this))
        
        this.agentPreview = new app.LoadedModules.AgentPreview(this.outputs.agentSampleCanvas, this.agentSprites)
        this.onChangeAgent()
        this.agentPreview.startRendering()
        this.agentPreview.animation = true

        this.models.keyframes.list('', null).then(data => data.payload).then(kflist => {
            this.outputs.keyframesSelector.fillOptions(kflist.map(item => {
                return({
                    markup: item.ekf_name,
                    value: item.ekf_uuid
                })
            }))
        })
        this.outputs.keyframesSelector.addEventListener('change',this.onChangeKeyframe.bind(this))

        this.kfArena = new app.LoadedModules.kfArena(this.outputs.kfArenaCanvas, this.agentSprites)
        this.kfArena.onclickAgent = this.onclickAgent.bind(this)
        this.kfArena.startRendering()
       
        this.outputs.btnAddAgent.disabled = true
        this.outputs.btnRemoveAgent.disabled = true
        this.outputs.btnSaveKF.disabled = true  
        this.outputs.kfName.addEventListener('keyup', this.updateKfButtons.bind(this))
        this.currentlySelectedAid = null
    }

    async onChangeAgent(event){
        if(this.outputs.agentsSelector.value) this.agentPreview.setAgent(this.outputs.agentsSelector.value)
        if(!this.outputs.agentsSelector.value) return

        if(this.notUserChange) {

        } else {
            this.currentAgentType = await this.models.agents.getProperties(this.outputs.agentsSelector.value)
            this.fillAgentProperties('', this.currentAgentType)
            // Deselect any on-scene selection
            if(this.currentlySelectedAid){
                this.kfArena.clearHighlight3DObj(this.kfArena.scene.getObjectByName(this.currentlySelectedAid), this.kfArena.scene)
            }
            this.currentlySelectedAid = null
        }
    }

    async onChangeKeyframe(event){
        if(!this.outputs.keyframesSelector.value) return
        let kfData = await this.models.keyframes.getKeyframe(this.outputs.keyframesSelector.value).then(data => data.payload)
        this.currentKeyframe = {
            kfId: kfData.info.ekf_uuid,
            kfName: kfData.info.ekf_name,
            prevKfId: kfData.info.ekf_prev_uuid,
        }
        this.outputs.kfName.value = kfData.info.ekf_name
        this.kfArena.reloadAgents(kfData.agents)
    }

    onclickAgent(obj3D){
        const aid = obj3D.name
        if(this.currentlySelectedAid == aid){ // Deselect
            this.kfArena.clearHighlight3DObj(obj3D, this.kfArena.scene)
            this.currentlySelectedAid = null
            this.outputs.btnRemoveAgent.disabled = true
        } else { // Select
            if(this.currentlySelectedAid){
                this.kfArena.clearHighlight3DObj(this.kfArena.scene.getObjectByName(this.currentlySelectedAid), this.kfArena.scene)
            }
            this.currentlySelectedAid = aid
            this.outputs.btnRemoveAgent.disabled = false
            if(this.kfArena.agents[aid]) {
                this.kfArena.highlight3DObj(obj3D, this.kfArena.scene)
                this.fillAgentProperties(aid, this.kfArena.agents[aid].props, this.kfArena.agents[aid].values)
                this.notUserChange = true
                this.outputs.agentsSelector.value = this.kfArena.agents[aid].type
                this.notUserChange = false
            }
        }
        this.updateKfButtons()
    }

    onAddAgent(event){
        //TODO prevent collisions !
        const AgentValues = this.getFieldsValues('div[data-output="agentProperties"]')
        const aid = this.newAgent(this.outputs.agentsSelector.value, AgentValues)
        this.output('agentId', `ID: ${aid}`)
        this.updateKfButtons()
    }

    onRemoveAgent(event){
        if(!this.currentlySelectedAid) return
        this.kfArena.removeAgent(this.currentlySelectedAid)
    }

    async newAgent(aType, AgentValues){
        const aid = crypto.randomUUIDv7()
        const agentProps = await this.models.agents.getProperties(aType)
        this.kfArena.addAgent(aType, aid, agentProps, AgentValues)
        return(aid)
    }

    updateKfButtons(){
        if((Object.keys(this.kfArena.agents).length > 0) && (this.outputs.kfName.value.length > 5)) { this.outputs.btnSaveKF.disabled = false  }
        else { this.outputs.btnSaveKF.disabled = true  }
    }

    onPropsChanged(evt, comp){
        if(this.currentlySelectedAid && this.kfArena.agents[this.currentlySelectedAid]){
            const AgentValues = this.getFieldsValues('div[data-output="agentProperties"]')
            this.kfArena.agents[this.currentlySelectedAid].values = AgentValues
            const val = Number.parseInt(comp.value, 10) 
            if((comp.name.startsWith('position.')) && (!Number.isNaN(val))){
                this.kfArena.moveAgent(this.currentlySelectedAid, {
                    x: this.getFieldValue('div[data-output="agentProperties"]', 'position.x'),
                    y: this.getFieldValue('div[data-output="agentProperties"]', 'position.y'),
                    z: this.getFieldValue('div[data-output="agentProperties"]', 'position.z'),
                })
            } else if((comp.name.startsWith('speed.')) && (!Number.isNaN(val))){
                this.kfArena.changeAgentSpeed(this.currentlySelectedAid, {
                    x: this.getFieldValue('div[data-output="agentProperties"]', 'speed.x'),
                    y: this.getFieldValue('div[data-output="agentProperties"]', 'speed.y'),
                    z: this.getFieldValue('div[data-output="agentProperties"]', 'speed.z'),
                })
            }
        }
    }

    fillAgentProperties(aid, agentProps, agentValues = {}){ 
        this.outputs.agentProperties.innerHTML = `<div data-output="agentId">ID: ${aid}</div>`
        this.outputs.agentProperties.append(...this.fieldsFromJSON(agentProps, agentValues, 'Internal properties', this.onPropsChanged.bind(this)))
        this.outputs.agentProperties.append(...this.fieldsFromJSON({
            "position.x": {
                label: "Position X",
                type: "number",
                default: "0"
            },
            "position.y": {
                label: "Position Y",
                type: "number",
                default: "0"
            },
            "position.z": {
                label: "Position Z",
                type: "number",
                default: "0"
            },
        }, agentValues, 'Coordinates', this.onPropsChanged.bind(this)))
        this.outputs.agentProperties.append(...this.fieldsFromJSON({
            "speed.x": {
                label: "Speed X",
                type: "number",
                default: "0"
            },
            "speed.y": {
                label: "Speed Y",
                type: "number",
                default: "0"
            },
            "speed.z": {
                label: "Speed Z",
                type: "number",
                default: "0"
            },
        }, agentValues, 'Speed vector', this.onPropsChanged.bind(this)))
        this.outputs.btnAddAgent.disabled = false
        this.setupRefs()
    }

    async onSaveKF(evt){
        let result = { success: true } 
        if(!this.currentKeyframe.kfId){ // Create first (and get new kfId)
            this.currentKeyframe.kfName = this.outputs.kfName.value
            result = await this.models.keyframes.create(this.currentKeyframe)
            this.currentKeyframe.kfId = result.payload.kfId
        } else if(this.currentKeyframe.kfName != this.outputs.kfName.value){ //rename 
            this.currentKeyframe.kfName = this.outputs.kfName.value
            result = await this.models.keyframes.rename(this.currentKeyframe)
        } 

        if(result.success){

            await this.models.keyframes.save(this.currentKeyframe.kfId, this.kfArena.agents)
            this.outputs.btnSaveKF.disabled = true 
            ui.growl.append('Keyframe saved!','success',3000)
            setTimeout(() => { this.outputs.btnSaveKF.disabled = false}, 3000)
        }
    }

}

app.registerClass('KeyframeView', KeyframeView)

//TODO :
/*

API update
API remove
API listAgentTypes
if unsavec changes in scene => confirm before reloading

agent rotation (param + tween)

Bugs

=> reselect same scene resets it


*/
