// dependency : dom.js, event.js

/* bloc */


	function Bloc(id, className, x, y, w, h, minWidth, minHeight, maxWidth, maxHeight)
    {
        this.id = id;
        this.htmlElement = dom.addElement(blocManager.htmlRootElement, "div");
        this.htmlElement.className = "bloc " + className;
        this.htmlElement.id = id;
        
        this.contentElement = false;

        this.minWidth = minWidth;
        this.minHeight = minHeight;
        this.maxWidth = maxWidth;
        this.maxHeight = maxHeight;

       	this.prefferedTop = y;
       	this.minTop = y;

        this.getTop = function() {return this.top;};
        this.getBottom = function() {return this.top + this.height;};
        this.getLeft = function() {return this.left;};
        this.getRight = function() {return this.left + this.width;};
        this.getWidth = function() {return this.width;};
        this.getHeight = function() {return this.height;};

		this.setTitle = function(newTitle)
		{
			dom.get(this.htmlElement.id + "Title").childNodes[0].data = newTitle;
		};

        this.setLeft = function(x)
        {
          	this.left = x;
          	this.htmlElement.style.left = this.left + "px";
        };

        this.setTop = function(y)
        {
          	this.top = y;
          	this.htmlElement.style.top = this.top + "px";
        };

        this.setWidth = function(w)
        {
          	if (this.minWidth != 0 && w < this.minWidth)
          	{
            	w = this.minWidth;
          	}
          	if (this.maxWidth != 0 && w > this.maxWidth)
          	{
            	w = this.maxWidth;
          	}
          	this.width = w;
          	this.htmlElement.style.width = this.width + "px";
          	if (this.contentElement)
          	{
	          	var contentWidth = w-15;
	          	if (contentWidth <0)
	          	{
	          		contentWidth = 0;
	          	}
	          	this.contentElement.style.width = contentWidth + "px";
          	}
        };

        this.setHeight = function(h)
        {
          	if (this.minHeight != 0 && h < this.minHeight)
          	{
            	h = this.minHeight;
          	}
          	if (this.maxHeight != 0 && h > this.maxHeight)
          	{
            	h = this.maxHeight;
          	}
          	this.height = h;
          	this.htmlElement.style.height = this.height + "px";
          	if (this.contentElement)
          	{
	          	var contentHeight = h-60;
	          	if (contentHeight <0)
	          	{
	          		contentHeight = 0;
	          	}
	          	this.contentElement.style.height = contentHeight + "px";
          	}
        };
        
		this.createDisplay = function(title, closeFunction)
		{
	        var titleElement = dom.addElement(this.htmlElement, "h2");
	        titleElement.id = this.htmlElement.id + "Title";
	        dom.addText(titleElement, title);
	        
        	var minimize = dom.addElement(this.htmlElement, "img");
        	minimize.src="core/image/layoutMinimize.gif";
        	minimize.className = "icon";
        	dom.addEvent(minimize, "click", function() {blocManager.minimizeBloc(this.parentNode.id)});

	        if (closeFunction)
	        {
	        	var close = dom.addElement(this.htmlElement, "img");
	        	close.src="core/image/layoutClose.gif";
	        	close.className = "icon";
	        	dom.addEvent(close, "click", closeFunction);

				minimize.style.top = "26px";
	        }
	        
	        this.contentElement = dom.addElement(this.htmlElement, "div");
	        this.contentElement.className = "blocContent";
	        this.contentElement.id = id + "Content";

	        var hResizer = dom.addElement(this.htmlElement, "div");
	        hResizer.className = "hResizer";
	
	        var vResizer = dom.addElement(this.htmlElement, "div");
	        vResizer.className = "vResizer";

	        var hvResizer = dom.addElement(this.htmlElement, "div");
	        hvResizer.className = "hvResizer";

	        addMouseHandler(titleElement,
	        	function(element, event) {blocManager.initMove(id, event)},
	            function(element, event) {blocManager.move(id, event)},
	            function(element, event) {blocManager.endMove(id, event)});
	        addMouseHandler(hResizer,
	            function(element, event) {blocManager.initResize(id, event, true, false)},
	            function(element, event) {blocManager.resize(id, event, true, false)},
	            function(element, event) {blocManager.endResize(id, event, true, false)});
	        addMouseHandler(vResizer,
	            function(element, event) {blocManager.initResize(id, event, false, true)},
	            function(element, event) {blocManager.resize(id, event, false, true)},
	            function(element, event) {blocManager.endResize(id, event, false, true)});
	        addMouseHandler(hvResizer,
	            function(element, event) {blocManager.initResize(id, event, true, true)},
	            function(element, event) {blocManager.resize(id, event, true, true)},
	            function(element, event) {blocManager.endResize(id, event, true, true)});
	            
	        this.setWidth(this.width);
	        this.setHeight(this.height);
		};
		
		this.createIconDisplay = function(id)
		{
	        this.id = id;
          var titleElement = dom.addElement(this.htmlElement, "h2");
	        titleElement.id = id + "Title";
	        
	        this.htmlElement.id = id;

        	var maximize = dom.addElement(this.htmlElement, "img");
        	maximize.src="core/image/layoutMaximize.gif";
        	maximize.className = "icon";
        	dom.addEvent(maximize, "click", function() {blocManager.maximizeBloc(id)});
        	maximize.style.right = "0px";
        	maximize.style.top = "0px";

	        addMouseHandler(titleElement,
	        	function(element, event) {blocManager.initMove(id, event)},
	            function(element, event) {blocManager.move(id, event)},
	            function(element, event) {blocManager.endMove(id, event)});
	        
		}

        this.setLeft(x);
        this.setTop(y);
        this.setWidth(w);
        this.setHeight(h);
        
      }
      
/* bloc manager */

	var blocManager = 
	{
	   	htmlRootElement: false,
    	blocs: new Array(),
    	indiceToId: new Array(),
    	moveBloc: false,
        virtualBloc: false,
        gridXSize: 34,
        gridYSize: 21,

        init: function()
        {
			this.htmlRootElement = document.getElementsByTagName("body")[0];
        },
        

		// here start blocs creators end removers
		
        createBloc: function(id, title, className, closeFunction, x, y, w, h, minWidth, minHeight, maxWidth, maxHeight)
        {
        	var bloc = new Bloc(id, className, this.roundLeft(x), this.roundTop(y), this.roundLeft(w)-1, this.roundTop(h)-1, this.roundLeft(minWidth)-1, this.roundTop(minHeight)-1, this.roundLeft(maxWidth)-1, this.roundTop(maxHeight)-1);
			    bloc.createDisplay(title, closeFunction);
			    this.blocs[id] = bloc;
          this.indiceToId[this.indiceToId.length] = id;
          this.refresh();

         	return bloc;
        },
        
        removeBloc: function(bloc)
        {
            this.htmlRootElement.removeChild(bloc.htmlElement);
            var id = bloc.id;
          	this.blocs[id] = null;
          	this.indiceToId.splice(this.getIndice(id), 1);
          	this.refresh();
        },
        
        hideBloc: function(bloc)
        {
      			bloc.htmlElement.style.display="none";
            var id = bloc.id;
          	this.blocs[id] = null;
          	this.indiceToId.splice(this.getIndice(id), 1);
          	this.refresh();
        },
        
        showBloc: function(bloc)
        {
            var id = bloc.id;
      			this.blocs[id] = bloc;
          	this.indiceToId[this.indiceToId.length] = id;
          	this.refresh();
          	bloc.htmlElement.style.display = "";
        },

        showVirtualBloc: function(fromBloc)
        {
        	this.virtualBloc = new Bloc("", "virtualBloc", fromBloc.getLeft(), fromBloc.getTop(), fromBloc.getWidth(), fromBloc.getHeight(), fromBloc.minWidth, fromBloc.minHeight, fromBloc.maxWidth, fromBloc.maxHeight);
        },
        
        hideVirtualBloc: function()
        {
			this.htmlRootElement.removeChild(this.virtualBloc.htmlElement);
        	this.virtualBloc = false;
        },

		minimizeBloc: function(id)
		{
			var bloc = this.blocs[id];
			bloc.htmlElement.style.display = "none";
			bloc.contentElement.id = "";
			bloc.htmlElement.id = "";

			var iconBloc = new Bloc("", bloc.htmlElement.className + " minimized", bloc.getLeft(), bloc.getTop(), 67, 41, 67, 41, 67, 41);			
			iconBloc.bloc = bloc;
			iconBloc.createIconDisplay(id);

			this.blocs[id] = iconBloc;
          	this.refresh();
			this.releasePrefferedTop();
		},
		
		maximizeBloc: function(id)
		{
			var iconBloc = this.blocs[id];
			this.htmlRootElement.removeChild(iconBloc.htmlElement);

			var bloc = iconBloc.bloc;
			bloc.setTop(iconBloc.getTop());
			bloc.setLeft(iconBloc.getLeft());
			bloc.prefferedTop = iconBloc.prefferedTop;
			bloc.htmlElement.style.display = "";
			bloc.contentElement.id = id + "Content";
			bloc.htmlElement.id = id;

			this.blocs[id] = bloc;
          	this.refresh();
			this.releasePrefferedTop();
		},
		
		// TODO not use : remove ?
        setSize: function(blocId, newWidth, newHeight)
        {
          	var bloc = this.blocs[blocId];
           	bloc.setWidth(this.roundLeft(newWidth)-1);
           	bloc.setHeight(this.roundTop(newHeight)-1);
          	this.refresh();
			this.releasePrefferedTop();
        },

		// here start the event handlers
		
        initMove: function(blocId, event)
        {
          	this.moveBloc = this.blocs[blocId];

          	this.showVirtualBloc(this.moveBloc);
          	this.virtualBloc.tempX = event.clientX - this.virtualBloc.left;
          	this.virtualBloc.tempY = event.clientY - this.virtualBloc.top;
          	this.virtualBloc.tempIndice = this.getIndice(this.moveBloc.id);

          	this.blocs[this.moveBloc.id] = this.virtualBloc;
        },

        move: function(blocId, event)
        {
          	var x = event.clientX - this.virtualBloc.tempX;
          	var y = event.clientY - this.virtualBloc.tempY;

          	this.moveBloc.setLeft(x);
          	this.moveBloc.setTop(y);

          	var newRoundLeft = this.roundLeft(x);
          	var newIndice = this.orderBlocs(this.moveBloc.id, x, y);
          	var prefferedTop = this.roundTop(y);

          	if (this.virtualBloc.tempIndice != newIndice || this.virtualBloc.left != newRoundLeft || this.virtualBloc.prefferedTop != prefferedTop)
          	{
            	this.virtualBloc.setLeft(newRoundLeft);
            	this.virtualBloc.tempIndice = newIndice;
            	this.virtualBloc.prefferedTop = prefferedTop;
            	this.refresh();
          	}
        },

        endMove: function(blocId, event)
        {
	        this.release();
        },

        initResize: function(blocId, event, resizeW, resizeH)
        {
          	this.moveBloc = this.blocs[blocId];
          	this.showVirtualBloc(this.moveBloc);

          	if (resizeW)
          	{
            	this.virtualBloc.tempX = event.clientX - this.virtualBloc.left - this.virtualBloc.width;
          	}
          	if (resizeH)
          	{
            	this.virtualBloc.tempY = event.clientY - this.virtualBloc.top - this.virtualBloc.height;
          	}

          	this.blocs[this.moveBloc.id] = this.virtualBloc;
        },

        resize: function(blocId, event, resizeW, resizeH)
        {
          	var newWidth = this.virtualBloc.width;
          	var newHeight = this.virtualBloc.height;

          	if (resizeW)
          	{
            	newWidth = event.clientX - this.virtualBloc.tempX - this.virtualBloc.left;
          	}
          	if (resizeH)
          	{
            	newHeight = event.clientY - this.virtualBloc.tempY - this.virtualBloc.top;
          	}

          	this.moveBloc.setWidth(newWidth);
          	this.moveBloc.setHeight(newHeight);

          	var newRoundWidth = this.roundLeft(newWidth)-1;
          	var newRoundHeight = this.roundTop(newHeight)-1;

          	if (this.virtualBloc.height != newRoundHeight || this.virtualBloc.width != newRoundWidth)
          	{
            	this.virtualBloc.setHeight(newRoundHeight);
            	this.virtualBloc.setWidth(newRoundWidth);
            	this.refresh();
          	}
        },
        
        endResize: function(blocId, event, resizeW, resizeH)
        {
	        this.release();
        },
        
        release: function()
        {
          	this.blocs[this.moveBloc.id] = this.moveBloc;

          	this.moveBloc.setLeft(this.virtualBloc.left);
          	this.moveBloc.setTop(this.virtualBloc.top);
          	this.moveBloc.setWidth(this.virtualBloc.width);
          	this.moveBloc.setHeight(this.virtualBloc.height);
          	this.moveBloc.prefferedTop = this.virtualBloc.prefferedTop;
          	this.moveBloc = false;

			this.releasePrefferedTop();
			this.hideVirtualBloc();
        },
        
        // here start the layout engine
        
        orderBlocs: function(id, xpos, ypos)
        {
          	var blocOldIndice = blocManager.getIndice(id);
          	var i = blocManager.indiceToId.length-1;
          	var indice = i+1;
          	while (i>=0)
          	{
            	var currentBloc = blocManager.blocs[blocManager.indiceToId[i]];
            	if (currentBloc.prefferedTop >= ypos && i != blocOldIndice)
            	{
              		indice = i;
            	}
            	i--;
          	}
          	if (indice < blocOldIndice)
          	{
            	blocManager.indiceToId.splice(blocOldIndice, 1);
            	blocManager.indiceToId.splice(indice, 0, id);
          	}
          	else if (blocOldIndice < indice)
          	{
            	blocManager.indiceToId.splice(indice, 0, id);
            	blocManager.indiceToId.splice(blocOldIndice, 1);
            	indice--;
          	}
          	return indice;
        },
        
        refresh: function()
        {
          	for (var i = 0; i < blocManager.indiceToId.length; i++)
          	{
            	var currentBloc = blocManager.blocs[blocManager.indiceToId[i]];
            	currentBloc.minTop = blocManager.getMinimalTop(i, currentBloc.getLeft(), currentBloc.getRight());
          	}
          
          	for (var i = blocManager.indiceToId.length - 1; i>=0; i--)
          	{
            	var currentBloc = blocManager.blocs[blocManager.indiceToId[i]];
            	if (currentBloc.prefferedTop < currentBloc.minTop)
            	{
            		currentBloc.setTop(currentBloc.minTop)
            	}
            	else
            	{
	           		currentBloc.setTop(this.getFinalTop(i, currentBloc.getLeft(), currentBloc.getRight(), currentBloc.prefferedTop, currentBloc.getHeight()));
	           	}
          	}
        },
        
        getMinimalTop: function(indice, xmin, xmax)
        {
          	var yPos = 0;
          	for (var i = 0; i< indice; i++)
          	{
            	var currentBloc = blocManager.blocs[blocManager.indiceToId[i]];
            	if (currentBloc.getRight() > xmin && currentBloc.getLeft() <= xmax)
            	{
              		if (currentBloc.minTop + currentBloc.height > yPos)
              		{
                		yPos = currentBloc.minTop + currentBloc.height;
              		}
            	}
          	}
          	return this.roundTop(yPos);
        },

        getFinalTop: function(indice, xmin, xmax, maxTop, height)
        {
          	var yPos = maxTop;
          	for (var i=indice + 1; i< blocManager.indiceToId.length; i++)
          	{
            	var currentBloc = blocManager.blocs[blocManager.indiceToId[i]];
            	if (currentBloc.getRight() > xmin && currentBloc.getLeft() <= xmax)
            	{
              		if (currentBloc.getTop() < yPos + height)
              		{
                		yPos = currentBloc.getTop() - height ;
              		}
            	}
          	}
         	return this.roundTop(yPos);
        },

        releasePrefferedTop: function()
        {
          	for (var i = 0; i < blocManager.indiceToId.length; i++)
          	{
	           	var currentBloc = blocManager.blocs[blocManager.indiceToId[i]];
	           	currentBloc.prefferedTop = currentBloc.getTop();
          	}
        },

		// here start utilities

        getIndice: function(id)
        {
          	for (var i = 0; i < blocManager.indiceToId.length; i++)
          	{
            	if (blocManager.indiceToId[i] == id)
            	{
	              	return i;
            	}
          	}
          	logger.error("[getIndice] id " + id + " not found... return false");
          	return false;
        },
        
        roundLeft: function(x)
        {
          return this.round(x, this.gridXSize);
        },

        roundTop: function(y)
        {
          return this.round(y, this.gridYSize);
        },
        
        round: function(value, gridSize)
        {
          return Math.floor((value + gridSize / 2) / gridSize) * gridSize;
        }
      }

    addLoadEvent(function() {blocManager.init() });
      
