define(['scripts/knockout-3.3.0','scripts/ACTComponent.js', 'scripts/ACTUtils'], function(ko, ACTComponent, ACTUtils) {

    function PanelComponentViewModel(params, element) {
		this.base = new ACTComponent($(element), params);

		this.components = ko.observableArray([]);
		this.componentModels = {}
		this.readyChildrenCount = 0;
		this.baseModel = params.baseModel;

		params.baseModel.beforeResizeFunctions.push(function() {
			var def = this.base.definition;
			if (def.WidthType == "FitToContent" || def.HeightType == "FitToContent")
				this.resizeChildren();
		}.bind(this));

		params.baseModel.resizeFunctions.push(function(h, w) {
			var def = this.base.definition;
			if (def.WidthType != "FitToContent" || def.HeightType != "FitToContent")
				this.resizeChildren();
		}.bind(this));

		params.baseModel.lockFunctions.push(function(lockKey, noLockPaths) {
			for (var key in this.componentModels) {
				this.componentModels[key].lock(lockKey, noLockPaths);
			}
		}.bind(this));

		params.baseModel.unlockFunctions.push(function(lockKey) {
			for (var key in this.componentModels) {
				this.componentModels[key].unlock(lockKey);
			}
		}.bind(this));

		params.baseModel.showFunctions.push(function() {
			// when we are show our children also gonna be shown if they are visible
			for (var key in this.componentModels)
				this.componentModels[key].callShowFunctions();
		}.bind(this));

		params.baseModel.hideFunctions.push(function() {
			// when we are show our children also gonna be hide if they were visible
			for (var key in this.componentModels)
				this.componentModels[key].callHideFunctions();
		}.bind(this));


		this.resizeChildren = function() {
			var $contentElements = $(".content");
			var oldOverflowState = ACTUtils.GetOverflowsAndSetThemTo($contentElements, "hidden")
            for (var key in this.componentModels) {
				ACTUtils.Log("set dirty: "+key, 1);
				this.componentModels[key].setDirty();
			}
			for (var key in this.componentModels) {
				ACTUtils.Log("resize component: "+key, 1);
				this.componentModels[key].resize();
			}
			ACTUtils.SetOverflows($contentElements, oldOverflowState);
		}.bind(this);
		
		this.registerComponentModel = function(name, component) {
			this.componentModels[name] = component;
		}

		this.componentReady = function(component, newVal) {
			if (newVal) {
				this.readyChildrenCount++;
			}
			else {
				this.readyChildrenCount--;
				params.ready(false);
			}
			if (this.readyChildrenCount==this.components().length) {
				params.ready(true);
			}

			if (this.readyChildrenCount > this.components().length)
				console.warn("Too much component are ready. That's not suppose to happen. The same component may exist multiple time that can come from Model.Id");
		}

		this.base.onRefresh = function(obj) {
			var components = obj.Components;
			if (ACTUtils.ListOfComponentAreEqual(this.components(), components)) {
				if (components.length == 0)
					params.ready(true);
				return;
			}

			params.ready(false);

			this.componentModels = {}
			this.readyChildrenCount = 0;
			for (var i=0;i<components.length;i++) {
				var c = components[i];
				c.gridPanel = this;
			}
			this.components(components);

			if (components.length == 0) {
				// following line will not be called if we are no children that get ready (registerComponent)
				params.ready(true);
			}
		}.bind(this);
		
		this.base.initialize();
    }

	return {
		createViewModel: function(params, componentInfo) {
            return new PanelComponentViewModel(params, componentInfo.element);
        }
	};

});

