Vn.ShelvesReport = new Class
({
	Extends: Vn.Report

	,nItem: -1
	,nColors: 5
	
	,open: function (batch)
	{
		this.batch = batch;
		this.title = batch.getValue ('title');
		this.maxAmount = batch.getValue ('max-amount');
		this.showPacking = batch.getValue ('show-packing');
		this.stack = batch.getValue ('stack');
	
		var query =
			'SELECT id, name, width, height, depth, max_height, tray_height, '+
			'first_tray_elevation, tray_density, vspacing, hspacing '+
				'FROM shelf WHERE id = #shelf; '+
			'CALL item_organizer (#wh, #date, #family, #filter)';
		
		this.conn.execQuery (query, this.onQueryExec.bind (this), this.batch);
	}
	
	,onQueryExec: function (resultSet)
	{
		// Fetch query data

		var res = resultSet.fetchResult ();
		res.next ();
		
		var maxWidth = 170;
		var maxHeight = 200;
		
		var scale = maxWidth / res.get ('width');
		
		if (res.get ('max_height') * scale > maxHeight)
			scale = maxHeight / res.get ('max_height');
		
		var shelf = this.shelf =
		{
			 width: res.get ('width') * scale
			,height: res.get ('height') * scale
			,depth: res.get ('depth') * scale
			,maxHeight: res.get ('max_height') * scale
			,trayHeight: res.get ('tray_height') * scale
			,firstTrayElevation: res.get ('first_tray_elevation') * scale
			,trayDensity: res.get ('tray_density') * scale
			,vspacing: res.get ('vspacing') * scale
			,hspacing: res.get ('hspacing') * scale
		};
		
		var items = this.items = [];
		var remainings = this.remainings = [];
		var res = resultSet.fetchResult ();
		
		if (res.data.length == 0)
		{
			Htk.Toast.showError (_('No items found, check that all fields are correct'));
			return;
		}
		
		var boxScale = scale * 10;
		
		while (res.next ())
		if (!this.maxAmount || res.get ('etiquetas') <= this.maxAmount)
		{
			items.push ({
				 id: res.get ('Id_Article')
				,name: res.get ('Article')
				,packing: res.get ('packing')
				,amount: res.get ('etiquetas')
				,boxHeight: res.get ('z') * boxScale
				,boxWidth: res.get ('x') * boxScale
				,boxDepth: res.get ('y') * boxScale
			});
		}
		else
		{
			remainings.push ({
				 id: res.get ('Id_Article')
				,name: res.get ('Article')
				,packing: res.get ('packing')
				,amount: res.get ('etiquetas')
			});
		}

		// Intializes the allocator
			
		alloc = this.alloc = new Vn.Allocator ();
		alloc.items = items;
		alloc.shelfFunc = this.drawShelf.bind (this);
		alloc.boxFunc = this.drawBox.bind (this);
		alloc.stack = this.stack;
		alloc.nTrays = Math.ceil (
			(shelf.height - shelf.firstTrayElevation) /
			(shelf.trayHeight + shelf.trayDensity)
		);
		alloc.width = shelf.width - shelf.hspacing * 2;
		alloc.depth = shelf.depth;
		alloc.trayHeight = shelf.trayHeight - shelf.vspacing;
		alloc.topTrayHeight = shelf.maxHeight - shelf.vspacing
			- shelf.firstTrayElevation - (alloc.nTrays - 1) * shelf.trayHeight;
		
		// Opens the report
		
		this.createWindow ();
	}
	
	,onWindowCreate: function ()
	{	
		// Remaining amount
		
		var remainings = this.remainings;
		
		if (remainings.length > 0)
		{
			var sheet = this.doc.createElement ('div');
			sheet.className = 'sheet';
			this.doc.body.appendChild (sheet);
			
			var title = this.doc.createElement ('h1');
			title.className = 'title';
			title.appendChild (this.doc.createTextNode (this.title));
			sheet.appendChild (title);
		
			var subtitle = this.doc.createElement ('h2');
			subtitle.className = 'subtitle';
			subtitle.appendChild (this.doc.createTextNode (_('Pallets')));
			sheet.appendChild (subtitle);
			
			var ul = this.doc.createElement ('ul');
			sheet.appendChild (ul);
	
			for (var i = 0; i < remainings.length; i++)
			{
				var li = this.doc.createElement ('li');
				ul.appendChild (li);

				var span = this.doc.createElement ('span');
				span.className = 'item-id';
				span.appendChild (this.doc.createTextNode (remainings[i].id.toLocaleString ()));
				li.appendChild (span);
			
				var span = this.doc.createElement ('span');
				span.className = 'item';
				span.appendChild (this.doc.createTextNode (remainings[i].name));
				li.appendChild (span);
				
				if (this.showPacking)
					span.appendChild (this.doc.createTextNode (' '+ remainings[i].packing));

				var span = this.doc.createElement ('span');
				span.className = 'amount';
				span.appendChild (this.doc.createTextNode (remainings[i].amount));
				li.appendChild (span);
			}
		}
		
		// Draws the shelves

		this.alloc.run ();
		this.drawShelfEnding ();
	}

	,drawShelf: function (allocator, item)
	{
		var shelf = this.shelf;

		var sheet = this.doc.createElement ('div');
		sheet.className = 'sheet';
		this.doc.body.appendChild (sheet);
		
		// Draws the title
		
		var pageNumber = this.doc.createElement ('h1');
		pageNumber.className = 'page-number';
		pageNumber.appendChild (this.doc.createTextNode (allocator.currentShelf + 1));
		sheet.appendChild (pageNumber);
		
		var title = this.doc.createElement ('h1');
		title.className = 'title';
		title.appendChild (this.doc.createTextNode (this.title));
		sheet.appendChild (title);
		
		var subtitle = this.doc.createElement ('h2');
		subtitle.className = 'subtitle';
		subtitle.appendChild (this.doc.createTextNode (item.id.toLocaleString ()));
		sheet.appendChild (subtitle);
		
		this.drawShelfEnding ();
		this.lastSubtitle = subtitle;

		// Draws the shelf
		
		var shelfDiv = this.shelfDiv = this.doc.createElement ('div');
		shelfDiv.className = 'shelf';
		shelfDiv.style.width = this.mm (shelf.width);
		shelfDiv.style.height = this.mm (shelf.maxHeight);
		sheet.appendChild (shelfDiv);

		// Draws trays

		var lastTrayY = shelf.firstTrayElevation;

		if (shelf.trayHeight > 0)
		while (lastTrayY + shelf.trayDensity < shelf.height)
		{
			var tray = this.doc.createElement ('div');
			tray.className = 'tray';
			tray.style.width = this.mm (shelf.width);
			tray.style.height = this.mm (shelf.trayDensity);
			tray.style.bottom = this.mm (lastTrayY);
			shelfDiv.appendChild (tray);

			lastTrayY += shelf.trayHeight + shelf.trayDensity;
		}
	}
	
	,drawShelfEnding: function ()
	{
		if (this.lastSubtitle)
			this.lastSubtitle.appendChild (
				this.doc.createTextNode (' - '+ this.lastItem.id.toLocaleString ()));
	}
	
	,mm: function (size)
	{
		return size.toFixed (2) +'mm';
	}

	,drawBox: function (allocator, item, amount)
	{
		if (item.boxWidth == 0 || item.boxHeight == 0)
			return;

		var shelf = this.shelf;

		var x = allocator.trayX + shelf.hspacing;
		var y = allocator.trayY
			+ shelf.firstTrayElevation + shelf.trayDensity
			+ allocator.currentTray * (shelf.trayHeight + shelf.trayDensity);

		var box = this.doc.createElement ('div');
		box.className = 'box';
		this.shelfDiv.appendChild (box);
		
		box.style.left = this.mm (x);
		box.style.bottom = this.mm (y);
		box.style.width = this.mm (item.boxWidth);
		box.style.height = this.mm (item.boxHeight);
	
		if (amount == 0)
			this.nItem++;

		var nColor = this.nItem % this.nColors;
		Vn.Node.addClass (box, 'color'+ nColor);

		if (amount == 0 || allocator.firstShelfBox)
		{
			var fontSize = item.boxWidth / 5.2;
			
			if (fontSize > item.boxHeight - 1)
				fontSize = item.boxHeight - 1;
		
			var boxLabel = this.doc.createElement ('div');
			boxLabel.className = 'box-label';
			boxLabel.style.fontSize = this.mm (fontSize);
			boxLabel.appendChild (this.doc.createTextNode (item.id.toLocaleString ()));
			box.appendChild (boxLabel);
		}

		this.lastItem = item;
	}
});

Vn.Allocator = new Class
({
	addShelf: function (item)
	{
		this.currentShelf++;
		this.firstShelfBox = true;
	
		if (this.shelfFunc)
			this.shelfFunc (this, item);
	}

	,addTray: function (item)
	{
		if (this.currentTray <= 0)
		{
			this.addShelf (item);
			this.currentTray = this.nTrays - 1;
		}
		else
			this.currentTray--;
		
		this.trayX = 0;
	}

	,addColumn: function (item)
	{
		if (this.trayX + this.columnWidth + item.boxWidth > this.width
		|| this.currentTray == -1)
			this.addTray (item);
		else
			this.trayX += this.columnWidth;

		this.trayY = 0;
		this.columnWidth = item.boxWidth;
		this.lastBoxWidth = item.boxWidth;
	}

	,addBox: function (item, amount)
	{
		var trayHeight = this.trayHeight;
	
		if (this.currentTray == this.nTrays - 1)
			trayHeight = this.topTrayHeight;

		if (this.trayY + item.boxHeight > trayHeight
		|| item.boxWidth > this.lastBoxWidth
		|| (!this.stack && amount == 0))
			this.addColumn (item);

		if (this.boxFunc)
			this.boxFunc (this, item, amount);

		this.trayY += item.boxHeight;
	
		if (item.boxWidth < this.lastBoxWidth)
			this.lastBoxWidth = item.boxWidth;
	}

	,run: function ()
	{
		this.firstShelfBox = false;
		this.currentShelf = -1;
		this.currentTray = -1;
		this.columnWidth = 0;
		this.lastBoxWidth = 0;
		this.trayX = 0;
		this.trayY = 0;
		this.remaining = false;

		for (var i = 0; i < this.items.length; i++)
		{
			var item = this.items[i];
			var boxIncrement = Math.floor (this.depth / item.boxDepth);
			
			if (boxIncrement < 1)
				boxIncrement = 1;
		
			for (var amount = 0; amount < item.amount; amount += boxIncrement)
			{
				this.addBox (item, amount);
				this.firstShelfBox = false;
			}
		}
	
		return this.currentShelf + 1;
	}
	
});