//
// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
// LICENSE: Atomic Game Engine Editor and Tools EULA
// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
//

import ScriptWidget = require("ui/ScriptWidget");
import ComponentInspector = require("./ComponentInspector");
import DataBinding = require("./DataBinding");
import CreateComponentButton = require("./CreateComponentButton");
import EditorEvents = require("editor/EditorEvents");

interface ComponentState {

    expanded: boolean;

}

interface NodeState {

    expanded: boolean;
    componentStates: { [id: number]: ComponentState };

}

class NodeInspector extends ScriptWidget {

    constructor() {

        super();

        this.subscribeToEvent(this, "WidgetEvent", (ev) => this.handleWidgetEvent(ev));
        this.subscribeToEvent("GizmoMoved", (ev) => this.handleGizmoModed(ev));
        this.subscribeToEvent("Update", (ev) => this.handleUpdate(ev));

    }

    handleUpdate(ev) {

        // to keep from spamming UI update we have a little delta on the gizmo updates
        if (!this.node) {
            this.gizmoMoved = false;
            return;
        }

        if (this.gizmoMoved) {

            if (this.updateDelta > 1.0) {

                this.updateDelta = 0.0;

            }
            else {

                this.updateDelta -= ev.timeStep;

            }

            if (this.updateDelta <= 0) {

                for (var i in this.bindings) {

                    this.bindings[i].setWidgetValueFromObject();

                }

                this.gizmoMoved = false;
                this.updateDelta = 0;

            }


        }

    }


    handleGizmoModed(ev) {

        if (!this.node) return;

        this.gizmoMoved = true;

        this.updateDelta += .3;

    }

    handleWidgetEvent(ev: Atomic.UIWidgetEvent) {

        var handled = false;

        for (var i = 0; i < this.bindings.length; i++) {

            if (this.bindings[i].handleWidgetEvent(ev)) {

                handled = true;

            }

        }

        // return handled
        return handled;

    }

    getPrefabComponent(node: Atomic.Node): Atomic.PrefabComponent {

        if (node.getComponent("PrefabComponent"))
            return <Atomic.PrefabComponent>node.getComponent("PrefabComponent");

        if (node.parent)
            return this.getPrefabComponent(node.parent);

        return null;

    }

    detectPrefab(node: Atomic.Node): boolean {

        if (node.getComponent("PrefabComponent"))
            return true;

        if (node.parent)
            return this.detectPrefab(node.parent);

        return false;

    }

    inspect(node: Atomic.Node) {

        this.bindings = new Array();

        this.node = node;

        return;

        /*
        this.subscribeToEvent(node, "SceneEditStateChange", (data) => this.handleSceneEditStateChangeEvent(data));

        this.isPrefab = this.detectPrefab(node);

        var fd = new Atomic.UIFontDescription();
        fd.id = "Vera";
        fd.size = 11;

        var nlp = new Atomic.UILayoutParams();
        nlp.width = 304;

        var nodeLayout = this.nodeLayout = new Atomic.UILayout();
        nodeLayout.spacing = 4;

        nodeLayout.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_GRAVITY;
        nodeLayout.layoutPosition = Atomic.UI_LAYOUT_POSITION_LEFT_TOP;
        nodeLayout.layoutParams = nlp;
        nodeLayout.axis = Atomic.UI_AXIS_Y;

        // node attr layout

        var nodeSection = new Atomic.UISection();
        nodeSection.id = "node_section";
        nodeSection.text = "Node";
        nodeSection.value = 1;
        nodeLayout.addChild(nodeSection);

        var attrsVerticalLayout = new Atomic.UILayout(Atomic.UI_AXIS_Y);
        attrsVerticalLayout.spacing = 3;
        attrsVerticalLayout.layoutPosition = Atomic.UI_LAYOUT_POSITION_LEFT_TOP;
        attrsVerticalLayout.layoutSize = Atomic.UI_LAYOUT_SIZE_AVAILABLE;

        nodeSection.contentRoot.addChild(attrsVerticalLayout);

        var attrs = node.getAttributes();

        for (var i in attrs) {

            var attr = <Atomic.AttributeInfo>attrs[i];

            if (attr.mode & Atomic.AM_NOEDIT)
                continue;

            var binding = DataBinding.createBinding(node, attr);

            if (!binding)
                continue;

            var attrLayout = new Atomic.UILayout();

            attrLayout.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_GRAVITY;

            var name = new Atomic.UITextField();
            name.textAlign = Atomic.UI_TEXT_ALIGN_LEFT;
            name.skinBg = "InspectorTextAttrName";

            if (attr.type == Atomic.VAR_VECTOR3 || attr.type == Atomic.VAR_COLOR ||
                attr.type == Atomic.VAR_QUATERNION) {
                attrLayout.axis = Atomic.UI_AXIS_Y;
                attrLayout.layoutPosition = Atomic.UI_LAYOUT_POSITION_LEFT_TOP;
                attrLayout.skinBg = "InspectorVectorAttrLayout";
            }


            var bname = attr.name;

            if (bname == "Is Enabled")
                bname = "Enabled";

            name.text = bname;
            name.fontDescription = fd;

            attrLayout.addChild(name);

            attrLayout.addChild(binding.widget);

            attrsVerticalLayout.addChild(attrLayout);

            this.bindings.push(binding);

        }

        // PREFAB

        if (this.isPrefab) {

            var name = new Atomic.UITextField();
            name.textAlign = Atomic.UI_TEXT_ALIGN_LEFT;
            name.skinBg = "InspectorTextAttrName";
            name.text = "Prefab"
            name.fontDescription = fd;

            var prefabLayout = new Atomic.UILayout();
            prefabLayout.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_GRAVITY;

            var saveButton = new Atomic.UIButton();
            saveButton.text = "Save";
            saveButton.fontDescription = fd;

            saveButton.onClick = () => {

                var prefabComponent = this.getPrefabComponent(this.node);

                if (prefabComponent) {

                    prefabComponent.savePrefab();

                    return true;

                }

            }

            var undoButton = new Atomic.UIButton();
            undoButton.text = "Undo";
            undoButton.fontDescription = fd;

            undoButton.onClick = () => {

                var prefabComponent = this.getPrefabComponent(this.node);

                if (prefabComponent) {

                    prefabComponent.undoPrefab();

                    // our components are now recreated
                    // need to handle this

                    return true;

                }

            }

            var breakButton = new Atomic.UIButton();
            breakButton.text = "Break";
            breakButton.fontDescription = fd;

            breakButton.onClick = () => {

                var prefabComponent = this.getPrefabComponent(this.node);

                if (prefabComponent) {

                    prefabComponent.breakPrefab();

                    prefabLayout.visibility = Atomic.UI_WIDGET_VISIBILITY_GONE;

                    return true;

                }

            }


            prefabLayout.addChild(name);
            prefabLayout.addChild(saveButton);
            prefabLayout.addChild(undoButton);
            prefabLayout.addChild(breakButton);

            attrsVerticalLayout.addChild(prefabLayout);

        }

        // COMPONENTS

        var components = node.getComponents();

        for (var i in components) {

            var component = components[i];

            //if (component.isTemporary())
            //  continue;

            var ci = new ComponentInspector();
            this.componentInspectors.push(ci);
            ci.id = "component_section_" + component.id;

            ci.inspect(component);

            nodeLayout.addChild(ci);

        }

        this.addChild(nodeLayout);

        var button = new CreateComponentButton(node);

        nodeLayout.addChild(button);

        for (var i in this.bindings) {
            this.bindings[i].setWidgetValueFromObject();
            this.bindings[i].objectLocked = false;
        }

        this.loadState();
        */

    }

    updateWidgetValues(components: boolean = false) {

        for (var i in this.bindings) {
            this.bindings[i].objectLocked = true;
            this.bindings[i].setWidgetValueFromObject();
            this.bindings[i].objectLocked = false;
        }

        if (components) {

            for (var i in this.componentInspectors) {

                this.componentInspectors[i].updateWidgetValues();

            }

        }

    }

    handleSceneEditStateChangeEvent(ev) {

        this.updateWidgetValues();

    }

    saveState() {

        var node = this.node;

        if (!node.scene)
            return;

        var nodeStates = NodeInspector.nodeStates[node.scene.id];

        if (!nodeStates)
            return;

        var state = nodeStates[node.id];

        if (!state) {

            state = nodeStates[node.id] = { expanded: true, componentStates: {} };

        }

        var section: Atomic.UISection = <Atomic.UISection>this.nodeLayout.getWidget("node_section");

        state.expanded = section.value ? true : false;

        var components = node.getComponents();

        for (var i in components) {

            var component = components[i];
            var cstate = state.componentStates[component.id];

            if (!cstate) {
                cstate = state.componentStates[component.id] = { expanded: false };
            }

            section = <Atomic.UISection>this.nodeLayout.getWidget("component_section_" + component.id);

            if (section)
                cstate.expanded = section.value ? true : false;

        }

    }

    loadState() {

        var node = this.node;

        // lookup in node states via scene id
        var nodeStates = NodeInspector.nodeStates[node.scene.id];

        if (!nodeStates) {
            nodeStates = NodeInspector.nodeStates[node.scene.id] = {};
        }

        // lookup by node id
        var state = nodeStates[node.id];

        if (!state) {

            // we don't have a state, so save default state
            this.saveState();

        } else {

            var section: Atomic.UISection = <Atomic.UISection>this.nodeLayout.getWidget("node_section");

            section.value = state.expanded ? 1 : 0;

            var components = node.getComponents();

            for (var i in components) {

                var component = components[i];

                var cstate = state.componentStates[component.id];
                section = <Atomic.UISection>this.nodeLayout.getWidget("component_section_" + component.id);

                if (cstate && section) {

                    section.value = cstate.expanded ? 1 : 0;

                }

            }

        }

    }


    isPrefab: boolean;
    node: Atomic.Node;
    nodeLayout: Atomic.UILayout;
    bindings: Array<DataBinding>;
    gizmoMoved = false;
    updateDelta = 0;
    componentInspectors: Array<ComponentInspector> = [];

    static nodeStates: { [sceneID: number]: { [nodeId: number]: NodeState } } = {};

}

export = NodeInspector;
