define(['ko','underscore','mageUtils','uiRegistry','uiEvents','uiClass','./links','../storage/local'],function(ko,_,utils,registry,Events,Class,links){'use strict';var Element;function observable(obj,key,value){var method=Array.isArray(value)?'observableArray':'observable';if(_.isFunction(obj[key])&&!ko.isObservable(obj[key])){return;} if(ko.isObservable(value)){value=value();} ko.isObservable(obj[key])?obj[key](value):obj[key]=ko[method](value);} function accessor(obj,key,value){if(_.isFunction(obj[key])||ko.isObservable(obj[key])){return;} obj[key]=value;if(!ko.es5.isTracked(obj,key)){ko.track(obj,[key]);}} Element=_.extend({defaults:{_requested:{},containers:[],exports:{},imports:{},links:{},listens:{},name:'',ns:'${ $.name.split(".")[0] }',provider:'',registerNodes:true,source:null,statefull:{},template:'',tracks:{},storageConfig:{provider:'localStorage',namespace:'${ $.name }',path:'${ $.storageConfig.provider }:${ $.storageConfig.namespace }'},maps:{imports:{},exports:{}},modules:{storage:'${ $.storageConfig.provider }'}},initialize:function(){this._super().initObservable().initModules().initStatefull().initLinks().initUnique();return this;},initObservable:function(){_.each(this.tracks,function(enabled,key){if(enabled){this.track(key);}},this);return this;},initModules:function(){_.each(this.modules,function(name,property){if(name){this[property]=this.requestModule(name);}},this);if(!_.isFunction(this.source)){this.source=registry.get(this.provider);} return this;},initContainer:function(parent){this.containers.push(parent);return this;},initStatefull:function(){_.each(this.statefull,function(path,key){if(path){this.setStatefull(key,path);}},this);return this;},initLinks:function(){return this.setListeners(this.listens).setLinks(this.links,'imports').setLinks(this.links,'exports').setLinks(this.exports,'exports').setLinks(this.imports,'imports');},initUnique:function(){var update=this.onUniqueUpdate.bind(this),uniqueNs=this.uniqueNs;this.hasUnique=this.uniqueProp&&uniqueNs;if(this.hasUnique){this.source.on(uniqueNs,update,this.name);} return this;},setStatefull:function(key,path){var link={};path=!_.isString(path)||!path?key:path;link[key]=this.storageConfig.path+'.'+path;this.setLinks(link,'imports').setLinks(link,'exports');return this;},setUnique:function(){var property=this.uniqueProp;if(this[property]()){this.source.set(this.uniqueNs,this.name);} return this;},requestModule:function(name){var requested=this._requested;if(!requested[name]){requested[name]=registry.async(name);} return requested[name];},getTemplate:function(){return this.template;},hasTemplate:function(){return!!this.template;},get:function(path){return utils.nested(this,path);},set:function(path,value){var data=this.get(path),diffs;diffs=!_.isFunction(data)&&!this.isTracked(path)?utils.compare(data,value,path):false;utils.nested(this,path,value);if(diffs){this._notifyChanges(diffs);} return this;},remove:function(path){var data=utils.nested(this,path),diffs;if(_.isUndefined(data)||_.isFunction(data)){return this;} diffs=utils.compare(data,undefined,path);utils.nestedRemove(this,path);this._notifyChanges(diffs);return this;},observe:function(useAccessors,properties){var model=this,trackMethod;if(typeof useAccessors!=='boolean'){properties=useAccessors;useAccessors=false;} trackMethod=useAccessors?accessor:observable;if(_.isString(properties)){properties=properties.split(' ');} if(Array.isArray(properties)){properties.forEach(function(key){trackMethod(model,key,model[key]);});}else if(typeof properties==='object'){_.each(properties,function(value,key){trackMethod(model,key,value);});} return this;},track:function(properties){this.observe(true,properties);return this;},isTracked:function(property){return ko.es5.isTracked(this,property);},_notifyChanges:function(diffs){diffs.changes.forEach(function(change){this.trigger(change.path,change.value,change);},this);_.each(diffs.containers,function(changes,name){var value=utils.nested(this,name);this.trigger(name,value,changes);},this);return this;},restore:function(){var ns=this.storageConfig.namespace,storage=this.storage();if(storage){utils.extend(this,storage.get(ns));} return this;},store:function(property,data){var ns=this.storageConfig.namespace,path=utils.fullPath(ns,property);if(arguments.length<2){data=this.get(property);} this.storage('set',path,data);return this;},getStored:function(property){var ns=this.storageConfig.namespace,path=utils.fullPath(ns,property),storage=this.storage(),data;if(storage){data=storage.get(path);} return data;},removeStored:function(property){var ns=this.storageConfig.namespace,path=utils.fullPath(ns,property);this.storage('remove',path);return this;},destroy:function(skipUpdate){this._dropHandlers()._clearRefs(skipUpdate);},_dropHandlers:function(){this.off();if(_.isFunction(this.source)){this.source().off(this.name);}else if(this.source){this.source.off(this.name);} return this;},_clearRefs:function(skipUpdate){registry.remove(this.name);this.containers.forEach(function(parent){parent.removeChild(this,skipUpdate);},this);return this;},bubble:function(){var args=_.toArray(arguments),bubble=this.trigger.apply(this,args),result;if(!bubble){return false;} this.containers.forEach(function(parent){result=parent.bubble.apply(parent,args);if(result===false){bubble=false;}});return!!bubble;},onUniqueUpdate:function(name){var active=name===this.name,property=this.uniqueProp;this[property](active);},cleanData:function(){if(this.source&&this.source.componentType==='dataSource'){if(this.elems){_.each(this.elems(),function(val){val.cleanData();});}else{this.source.remove(this.dataScope);}} return this;},cacheData:function(){this.cachedComponent=utils.copy(this);},updateConfig:function(oldValue,newValue,path){var names=path.split('.'),index=_.lastIndexOf(names,'config')+1;names=names.splice(index,names.length-index).join('.');this.set(names,newValue);return this;}},Events,links);return Class.extend(Element);});