/* global EmptyRelationship, User, CollapsiblePanel */
var SensorDiscovery = Namespace.declare("com.ceruleanCircle.EAM.3_services",
    //simplified implementation of https://www.w3.org/TR/generic-sensor/

    class SensorDiscovery extends Interface {

        constructor() {
            super();
            Thinglish.defineAlias(this, "model.value");
            Thinglish.defineAlias(this, "model.range");
            Thinglish.defineAlias(this, "model.range.from");
            Thinglish.defineAlias(this, "model.range.to");
            Thinglish.defineAlias(this, "model.unit");
        }


        static get defaultImplementationClass() {
            return DefaultSensor;
        }

        static get dependencies() {
            return this.defaultImplementationClass.dependencies;
        }

        static get weBeanUnitPaths() {
            return this.defaultImplementationClass.weBeanUnitPaths;
        }

        static get overwriteServerDescriptor() {
            return this.defaultImplementationClass.overwriteServerDescriptor;
        }

        static get eamLayer() {
            return 3;
        }

        sensorSpecification() {
            return this.model.specification;
        }


        isActivated() {
            return this.activated;
        }

        get activated() {
            return this.state === "activated" ? true : false;
        }

        get hasReading() {
            return this.model.lastReading ? true : false;
        }

        get timestamp() {
            if (!this.hasReading)
                return this.model.lastReading.timestamp;
        }

        get state() {
            return this.model.state;
        }

        start() {
            if (this.state.startsWith("activ")) return;
            this.model.state = "activating";
            this.onactivate(event, this.model.state);
            this.model.timerId = setInterval(this.read.bind(this), this.model.specification.interval);
            this.model.state = "activated";
            this.onactivate(event, this.model.timerId);
        }

        stop() {
            if (this.state === "idle") return;
            clearInterval(this.model.timerId);
            this.model.state = "idle";
            this.model.timerId = { name: "sensor idle" };
        }

        onactivate(event, result) {
            this.eventSupport.fire("onActivate", this, result);
            return result;
        }
        onerror(event, result) {
            this.eventSupport.fire("onError", this, result);
            return result;
        }
        onreading(event, result) {
            this.eventSupport.fire("onReading", this, result);
            return result;
        }

        get defaultModel() {
            return {
                id: "ID: ideally should be this.model.id = device.connect(this);",

                name: "Sensor Interface Default-Model",
                description: "overwrite its values with the Sensors secific ones",
                badge: "mock",
                state: "idle",

                value: "theSensorValue: this.model.value",
                timestamp: null,

                specification: {
                    name: "Sensor Specification",
                    range: { name: "Sensor Range", from: 0, to: 100, steps: 10 },
                    unit: "??C",
                    interval: 1000,
                    description: "textual long description of the sensor",
                },
                lastReading: { name: "not yet read" },
                timerId: { name: "not yet started" },

                device: { name: "No Device" },
                ior: EmptyRelationship.of(IOR),
                autoUpdate: true

            };
        }

        async read() {
            let result = this.ucpModel.value.lastReading = await this.model.ior.load();
            this.ucpModel.value.lastReading = this.onreading(event, result)
            return this.model.lastReading;
        }

        static get WORKFLOW_SELECT() { return "actionId:protected:IdealComponent.startSelectWorkflow[Select]"; }
        static get WORKFLOW_ASSIGN() { return "actionId:protected:IdealComponent.assign[Choose this]:success"; }
        static get ACTION_CLEAR() { return "actionId:protected:IdealComponent.setEmpty[Remove]:success"; }
    }
);


var DefaultSensor = Namespace.declare("com.ceruleanCircle.EAM.2_systems",
    class DefaultSensor extends UcpComponent {
        static get implements() {
            if (!window["Sensor"]) {
                    window["Sensor"] = class Sensor extends Interface {};
            }
            return [Sensor, SensorDiscovery];
        }

        static get overwriteServerDescriptor() {
            return true;
        }

        static get dependencies() {
            return [
                //"/EAMD.ucp/Components/com/twitter/Bootstrap/Accordion/CollapsiblePanel/3.3.7/CollapsiblePanel.component.xml",
            ];
        }

        static get weBeanUnitPaths() {
            return null;
            return [
                "src/html/weBeans/" + this.name + ".weBean.html",
                //"src/html/weBeans/IdealComponentMinimalItemView.weBean.html",
                //"src/html/weBeans/IdealComponentMinimalDetailsView.weBean.html"
            ];
        }

        static start() {}

        constructor() {
            super();
        }

        init() {
            super.init();

            var model = this.defaultModel;
            model.sensorAdapter = undefined;
            this.model = model;

            this.actionIndex = Thinglish.createActionIndexOf(Sensor, this);

            return this;
        }


        get sensorAdapter() {
            if (this.model && this.ucpModel.value.sensorAdapter) {
                return this.ucpModel.value.subComponent;
            }
            //const newComponent = new CollapsiblePanel().init();
            //configure subComponent
            //newComponent.name = "new Subcomponent";
            //this.model.subComponent = newComponent;

            return null;
        }

        set sensorAdapter(newComponent) {
            this.ucpModel.value.sensorAdapter = newComponent;
        }

        /*
        onInitDetails(view) {
           console.info("ucpComponent onInitDetails",view.id,  ...arguments);
           this.details.model.heading = "Details initialized";

           console.info(`
           In the DefaultView WeBean IdealComponent.weBean.html a webean-property="details" ist declared on
                <bootstrap-collapsible-panel heading="Details" webean-property="details">

           this.details gives you access to the ucpView of that CollapsiblePanel
           this.detailsElement gives you access to  this.details.documentElement in the DOM          
           
           initalize any DOM listeners here.
           the method will be called after every new rendering
           `);
        }
        */

        onDomReady(view) {
            console.info("ucpComponent onDomReady", this.id, ...arguments);
            console.info("ucpComponent onDomReady - view:", this.id, view.id, view.documentElement);
            console.info(`
           the view is fully rendered and available in the DOM.

           initalize any DOM listeners here.
           the method will be called after every new rendering
           `);
        }


        /*
        loadWeBean() {
            if (Thinglish.lookupInObject(Relationship, "type.ucpComponentDescriptor.webBeanUnits"))
                return Relationship.type.ucpComponentDescriptor.webBeanUnits.find(u => u.model.name.startsWith(Relationship.name)).weBean;

            return null;
        }
        */

        updateView(view, updateObject) {
            console.info("ucpComponent updateView", this.id, ...arguments);

            console.info(`
           notifies you which view has to be rerendered.
           calling this.update() will force a complete rerendering.

           this implies loosing all DOM listeners. after rerendering onDomReady(view) will be called again to reinatialize DOM listeners

           calling tis.documentElement does the first rendering.
           the framework tries to postpone this step to the last possible point so that you can initialize the model first and 
           do not have to rerender many times. the last possible point to render, is if the element will be appended to to an element
           that is already in the DOM. The UcpView method checkTargetElement finds out if an element isInDom and ataches the boolean to the element.

           alternatively you can check the updateObject to see what in the model did change
           and update the dom manually here on view.documentElement or view.subViewElement

           view.subView gives you access to ucpViews declared as webeanProperties in the weBean
           `, this.id, ...arguments);

            if (!updateObject) {
                return;
            }
            Object.keys(updateObject).forEach(
                member => {
                    switch (member) {
                        case "attribute1":
                            //update something for attribute1
                            break;
                        case "property1":
                            //update something for property1
                            break;
                        default:
                            //update something in any case
                    }
                }
            );
        }

        handleSelection(event, item) {
            console.info(this.constructor.name, "selected", item.ucpComponent);
            Action.do(DetailsView.ACTION_SHOW, this);
            //Action.do(Workflow.ACTION_SELECT, item);
        }

        /*
            createOverView() {
                return new IdealComponentMinimalItemView();
            }
            createDetailsView() {
                return new IdealComponentMinimalDetailsView();
            }
        */
        startSelectWorkflow() {
            console.info(this.constructor.name, "startSelectWorkflow");
        }

        assign() {
            console.info(this.constructor.name, "assign");
        }

        setEmpty() {
            console.info(this.constructor.name, "setEmpty");
        }
    }
);

/*
var IdealComponentMinimalItemView = Namespace.declare("tla.EAM.layer5",
    class IdealComponentMinimalItemView extends UcpView {
        static get implements() { return [ItemView]; }

        init(ucpComponent) {
            super.init(ucpComponent);
            this.badge = "some Value";
            return this;
        }

        update(updateObject) {
            console.info("ucpView update", this.id, ...arguments);
            if (!updateObject) {
                return;
            }
            Object.keys(updateObject).forEach(
                member => {
                    switch (member) {
                        case "badge":
                            //update something for badge
                            break;
                        case "attribute1":
                            //update something for attribute1
                            break;
                        default:
                            //update something in any case
                    }
                }
            );
        }

    }
);


var IdealComponentMinimalDetailsView = Namespace.declare("tla.EAM.layer5",
    class IdealComponentMinimalDetailsView extends UcpView {
        static get implements() { return [DetailsView]; }

        init(ucpComponent) {
            super.init(ucpComponent);

            return this;
        }

        update(updateObject) {
            console.info("ucpView update", this.id, ...arguments);
        }

        onInitDetails() {
            console.info("ucpView onInitDetails", this.id, ...arguments);
            this.details.model.heading += " also from DetailsView";

        }

    }
);
*/