            var mypath = "";
            var mygrid = {};
            var mydata = [];
            var myhash = {};
            var myfacade = {};
            var mymsg = "";


define([
	"dojo/_base/declare",
    "dojo/dom-construct",
	"MW/dialog/DialogUtils",
	"dojo/i18n!cswebview/app/l10n/nls/app",
    "MW/facade/MatlabFacade",
    "dojo/parser", "dojo/on",
    "dgrid/Grid","dgrid/extensions/DijitRegistry","dgrid/extensions/ColumnHider","dgrid/Selection","dgrid/extensions/ColumnResizer",
    "dijit/form/Select","dijit/form/TextBox","dijit/form/CheckBox", "dijit/form/NumberSpinner", "dijit/form/Textarea","dijit/form/SimpleTextarea","dijit/form/ComboBox","dijit/form/NumberTextBox","dijit/form/ValidationTextBox",
    "dijit/layout/ContentPane","dojox/layout/TableContainer","dijit/TitlePane"
], function (declare, domConstruct, DialogUtils,appL10n,
             MatlabFacade,
             parser,on,
             Grid, DijitRegistry,Hider,Selection,ColumnResizer,
             Select, TextBox, CheckBox, NumberSpinner, Textarea, SimpleTextarea, ComboBox, NumberTextBox, ValidationTextBox,
             ContentPane, TableContainer, TitlePane
            ) {
	return declare(null, {
	    constructor: function(rootNode) {
	        this.domNode = rootNode;
	    },
		
		start: function () {
            
			
			// var node = domConstruct.create("div", { innerHTML: appL10n.helloWorld + "aa"});
 			// domConstruct.place(node, this.domNode);
			
			// DialogUtils.displayModalDialog(appL10n.helloWorld, appL10n.dialogTitle, null);



              
              mytest = [{"id":1,"status":1,"name":"StartTime","fullname":"Solver:StartTime1","type":"struct","prompt":"Start time:","tooltip":"Simulation start time. Note that the values that you specify\nas block initial conitions must be their values at this time.","component":"Solver","dependency":"","value": [{"a":true, "b":5, "c":"hello", "d":{"x":1,"y":2}, "e":[3, 4, "one", "two", {"r":true, "t":0}]}, "string", true ]
              },
              {"id":2,"status":0,"name":"StopTime","fullname":"Solver:StopTime1","type":"struct","prompt":"Stop time:","tooltip":"Simulation start time. Note that the values that you specify\nas block initial conitions must be their values at this time.","component":"Solver","dependency":"", "value": [{"asdfsdfasdfasdf234234234234asdf":true, "b":5, "c":"hello", "d":{"x":1,"y":2}, "e":[3, 4, "one", "two", {"r":true, "t":0}]}, "string124", true ]
              },
              {"id":3,"status":0,"name":"AA","fullname":"Solver:AA","type":"struct","prompt":"Stop time:","tooltip":"Simulation start time. Note that the values that you specify\nas block initial conitions must be their values at this time.","component":"Solver","dependency":"", "value": "7" },
              {"id":4,"status":0,"name":"BB","fullname":"Solver:BB","type":"struct","prompt":"Stop time:","tooltip":"Simulation start time. Note that the values that you specify\nas block initial conitions must be their values at this time.","component":"Solver","dependency":"", "value": {"a":"s","b":"y"} },

              ];
              


            function sendMsg(msg) {
                myfacade.publish(mypath+"/callback", msg);
            }

            
            var MyGrid = dojo.declare([Grid,DijitRegistry,Hider,ColumnResizer]);
            
            myhash = genHash(mydata);
            mypath = location.search.substring(1);
            myfacade = new MatlabFacade();
            establishConnection(mypath);

            var mycols = [
                {label: "Parameter", field: "prompt", renderCell: actionRenderName, sortable: false, unhidable:true},
                // {label: "Parameter", field: "prompt", sortable: true, unhidable:true},
                
                {label: "Value", field: "value", renderCell: actionRenderValue, sortable: false, unhidable:true},
                {label: "Name", field: "name", sortable: false, hidden:true},
                {label: "Component", field: "component", sortable: false, hidden:true},
                // {label: "Type", field: "type", sortable: false, hidden:true},
                // {label: "Status", field: "status", sortable: false, hidden:true},
                // {label: "Dependency Information", field: "dependency", sortable: true, hidden:true, renderCell:function(object, data, cell){cell.innerHTML = data;} },
            ];

            mygrid = new MyGrid({
                columns: mycols
            }, "root");

            // mygrid.startup();
            

            // mygrid.renderArray(mydata);


            // functions ...

            function genHash(data) {
                var hash = {};
                for (var i = 0, l = data.length; i < l; i++) {
                    var p = data[i];
                    hash[p.fullname] = i;
                }
                return hash;
            }

            function init() {
                mygrid.renderArray(mydata);
            }

            function callback(object, data) {
                object.value = data.value;
                myfacade.publish(mypath+"/callback", data);
            }

            function establishConnection(path) {
                mypath = path;
                
                var init = myfacade.subscribe(mypath+"/init", function (message) {
                    mydata = JSON.parse(message.data);
                    myhash = genHash(mydata);
                    mygrid.refresh();
                    mygrid.renderArray(mydata);

                    var update = myfacade.subscribe(mypath+"/update", function (message) {
                        var p = JSON.parse(message.data);
                        if (myhash.hasOwnProperty(p.fullname)) {
                            var i = myhash[p.fullname];
                            if (JSON.stringify(mydata[i]) == JSON.stringify(p)) {
                                return;  // prevent self-circle
                            }
                            mydata[i] = p;
                        } else {
                            var n = mydata.length;
                            myhash[p.fullname] = n;
                            mydata[n] = p;
                        }
                        
                        var pane = dijit.registry.byId(p.fullname);
                        updatePane(pane, p);
                    });

                    var refresh = myfacade.subscribe(mypath+"/refresh", function (message) {
                        mydata = JSON.parse(message.data);
                        myhash = genHash(mydata);
                        var x = mygrid.bodyNode.scrollLef;
                        var y = mygrid.bodyNode.scrollTop;
                        mygrid.refresh();
                        mygrid.renderArray(mydata);
                        mygrid.scrollTo({x:x, y:y})
                    });

                    var destroy = myfacade.subscribe(mypath+"/destroy", function (message) {
                        mygrid.refresh();
                    });
                    
                });

                myfacade.publish(mypath, "ready");


            }

            function scroll(n) {
                var y1 = mygrid.row(n-1).element.getBoundingClientRect().top;
                var y2 = mygrid.row(0).element.getBoundingClientRect().top;
                mygrid.scrollTo({y:y1-y2});

            }


            function actionRenderName(object, data, cell) {
                var name = '<div class="name">' + object.prompt + '</div>';
                var dscr = '<div class="dscr">' + object.tooltip; + '</div>';
                cell.innerHTML = '<div class="param" id="'+object.name+'_param">' + name  +'<br>'+ dscr + '&nbsp; '+ '</div>';
            }

            function actionRenderValue(object, data, cell) {
                var pane = dijit.registry.byId(object.fullname);
                if (pane) {
                    updatePane(pane, object);
                } else {
                    pane = createPane(object);
                }
                pane.placeAt(cell);
            }

            function createPane(object) {
                var pane =  new dijit.layout.ContentPane({id:object.fullname});
                var w = createWidget(object);
                w.placeAt(pane);
                return pane;
            }

            function updatePane(pane, object) {
                var w;
                switch (object.type) {
                case "enum":
                case "int" :
                case "boolean":
                case "string":
                case "minmax":
                    var id = object.fullname + "_value";
                    w = dijit.registry.byId(id);
                    if (w) {
                        updateWidget(w, object);
                    } else {
                        w = createWidget(object);
                        w.placeAt(pane);
                    }
                    break;
                default:
                    pane.destroyDescendants();
                    w = createWidget(object);
                    w.placeAt(pane);
                }
            }
            
            function createWidget (object) {
                var id = object.fullname + "_value";
                var w = dijit.registry.byId(id);
                if (w) {
                    return w;
                }

                // console.log(object.name);
                switch (object.type) {
                case "enum":
                    w = new dijit.form.Select({id:id, value:object.value, options:JSON.parse(JSON.stringify(object.options)),style:{width:'100px'}});
                    on(w, "change", function () {callback(object, {name:object.name, value:w.value});});
                    break;
                case "int":
                    w = new dijit.form.NumberTextBox({id:id, value:object.value,invalidMessage:"Only accepts numbers"});
                    on(w, "change", function () {callback(object, {name:object.name, value:w.value});});
                    break;
                case "boolean":
                    w = new dijit.form.CheckBox({id:id, checked:object.value});
                    on(w, "change", function () {callback(object, {name:object.name, value:w.checked});});
                    break;
                case "string":
                    if (object.value instanceof Array) {
                        object.value = "";
                    }
                    
                    w = new dijit.form.TextBox({id:id, value:object.value, placeHolder:"<empty>"});
                    on(w, "change", function () {callback(object, {name:object.name, value:w.value});});
                    break;
                case "minmax":
                    w = new dijit.form.NumberSpinner({intermediateChanges:false,id:id, value:object.value, constraints:{min:object.min, max:object.max}});
                    on(w, "change", function () {callback(object, {name:object.name, value:w.value});});
                    break;
                default:
                    w = getAutoWidget(object.value, object.status, object, "value", object);
                    break;
                }
                w.set("disabled", object.status > 0, false);
                return w;
            }

            function getAutoWidget(value, status, ref, id, param){
                var t;
                var w;
                if (value instanceof Array) {
                    t = new dijit.TitlePane({open:true,title:"Array ["+value.length+"]"});
                    w = new dojox.layout.TableContainer({"labelWidth":"1%",customClass:"myclass"});
                    for (var i = 0; i < value.length; i++) {
                        var c = getAutoWidget(value[i], status, value, i, param);
                        c.set('label', '#'+(i+1)+":", false);
                        w.addChild(c);
                    }
                    w.placeAt(t);
                    w.startup();
                    w.set("disabled", status > 0);
                }else if(value instanceof Object) {
                    t = new dijit.TitlePane({open:true,title:"Object"});
                    w = new dojox.layout.TableContainer({"labelWidth":"1%",customClass:"myclass"});
                    for (var k in value) {
                        var c =  getAutoWidget(value[k], status, value, k, param);
                        c.set('label', k+":", false);
                        w.addChild(c);
                    }
                    w.placeAt(t);
                    w.startup();
                    w.set("disabled", status > 0);
                }else if(value.constructor === Number) {
                    t = new dijit.form.NumberTextBox({value:value,invalidMessage:"Only accepts numbers"});

                    on(t, "change", function () {
                        ref[id] = t.value;
                        sendMsg({name:param.name, value:param.value});
                    });
                }else if(value.constructor === String) {
                    t = new dijit.form.TextBox({value:value});

                    on(t, "change", function () {
                        ref[id] = t.value;
                        sendMsg({name:param.name, value:param.value});
                    });
                }else if(value.constructor === Boolean) {
                    t = new dijit.form.CheckBox({checked:value});
                    
                    on(t, "change", function () {
                        ref[id] = t.checked;
                        sendMsg({name:param.name, value:param.value});
                    });
                }

                t.set("disabled", status > 0);
                return t;
            }

            function updateWidget (w, object) {
                if (object.fullname == "Solver:Solver") {
                    w.options = JSON.parse(JSON.stringify(object.options));
                    w.startup();
                }
                
                if (w instanceof dijit.form.CheckBox) {
                    w.set("checked", object.value, false);
                } else {
                    w.set("value", object.value, false);
                }
                w.set("disabled", object.status > 0, false);
            }


            



            
		},
		
		
	});
});
