/* jslint node: true */
'use strict';

var TraversalTracker = require('./traversalTracker');

/**
* Creates an instance of DocumentContext - a store for current x, y positions and available width/height.
* It facilitates column divisions and vertical sync
*/
function DocumentContext(pageSize, pageMargins) {
	this.pages = [];

	this.pageMargins = pageMargins;

	this.x = pageMargins.left;
	this.availableWidth = pageSize.width - pageMargins.left - pageMargins.right;
	this.availableHeight = 0;
	this.page = -1;

	this.snapshots = [];

	this.endingCell = null;

  this.tracker = new TraversalTracker();

	this.addPage(pageSize);
}

DocumentContext.prototype.beginColumnGroup = function() {
	this.snapshots.push({
		x: this.x,
		y: this.y,
		availableHeight: this.availableHeight,
		availableWidth: this.availableWidth,
		page: this.page,
		bottomMost: { y: this.y, page: this.page },
		endingCell: this.endingCell,
		lastColumnWidth: this.lastColumnWidth
	});

	this.lastColumnWidth = 0;
};

DocumentContext.prototype.beginColumn = function(width, offset, endingCell) {
	var saved = this.snapshots[this.snapshots.length - 1];

	this.calculateBottomMost(saved);

  this.endingCell = endingCell;
	this.page = saved.page;
	this.x = this.x + this.lastColumnWidth + (offset || 0);
	this.y = saved.y;
	this.availableWidth = width;	//saved.availableWidth - offset;
	this.availableHeight = saved.availableHeight;

	this.lastColumnWidth = width;
};

DocumentContext.prototype.calculateBottomMost = function(destContext) {
	if (this.endingCell) {
		this.saveContextInEndingCell(this.endingCell);
		this.endingCell = null;
	} else {
		destContext.bottomMost = bottomMostContext(this, destContext.bottomMost);
	}
};

DocumentContext.prototype.markEnding = function(endingCell) {
	this.page = endingCell._columnEndingContext.page;
	this.x = endingCell._columnEndingContext.x;
	this.y = endingCell._columnEndingContext.y;
	this.availableWidth = endingCell._columnEndingContext.availableWidth;
	this.availableHeight = endingCell._columnEndingContext.availableHeight;
	this.lastColumnWidth = endingCell._columnEndingContext.lastColumnWidth;
};

DocumentContext.prototype.saveContextInEndingCell = function(endingCell) {
	endingCell._columnEndingContext = {
		page: this.page,
		x: this.x,
		y: this.y,
		availableHeight: this.availableHeight,
		availableWidth: this.availableWidth,
		lastColumnWidth: this.lastColumnWidth
	};
};

DocumentContext.prototype.completeColumnGroup = function() {
	var saved = this.snapshots.pop();

	this.calculateBottomMost(saved);

	this.endingCell = null;
	this.x = saved.x;
	this.y = saved.bottomMost.y;
	this.page = saved.bottomMost.page;
	this.availableWidth = saved.availableWidth;
	this.availableHeight = saved.bottomMost.availableHeight;
	this.lastColumnWidth = saved.lastColumnWidth;
};

DocumentContext.prototype.addMargin = function(left, right) {
	this.x += left;
	this.availableWidth -= left + (right || 0);
};

DocumentContext.prototype.moveDown = function(offset) {
	this.y += offset;
	this.availableHeight -= offset;

	return this.availableHeight > 0;
};

DocumentContext.prototype.initializePage = function() {
	this.y = this.pageMargins.top;
	this.availableHeight = this.getCurrentPage().pageSize.height - this.pageMargins.top - this.pageMargins.bottom;
	this.pageSnapshot().availableWidth = this.getCurrentPage().pageSize.width - this.pageMargins.left - this.pageMargins.right;
};

DocumentContext.prototype.pageSnapshot = function(){
  if(this.snapshots[0]){
    return this.snapshots[0];
  } else {
    return this;
  }
};

DocumentContext.prototype.moveTo = function(x,y) {
	if(x !== undefined && x !== null) {
		this.x = x;
		this.availableWidth = this.getCurrentPage().pageSize.width - this.x - this.pageMargins.right;
	}
	if(y !== undefined && y !== null){
		this.y = y;
		this.availableHeight = this.getCurrentPage().pageSize.height - this.y - this.pageMargins.bottom;
	}
};

DocumentContext.prototype.beginDetachedBlock = function() {
	this.snapshots.push({
		x: this.x,
		y: this.y,
		availableHeight: this.availableHeight,
		availableWidth: this.availableWidth,
		page: this.page,
		endingCell: this.endingCell,
		lastColumnWidth: this.lastColumnWidth
	});
};

DocumentContext.prototype.endDetachedBlock = function() {
	var saved = this.snapshots.pop();

	this.x = saved.x;
	this.y = saved.y;
	this.availableWidth = saved.availableWidth;
	this.availableHeight = saved.availableHeight;
	this.page = saved.page;
	this.endingCell = saved.endingCell;
	this.lastColumnWidth = saved.lastColumnWidth;
};

function pageOrientation(pageOrientationString, currentPageOrientation){
	if(pageOrientationString === undefined) {
		return currentPageOrientation;
	} else if(pageOrientationString === 'landscape'){
		return 'landscape';
	} else {
		return 'portrait';
	}
}

var getPageSize = function (currentPage, newPageOrientation) {

	newPageOrientation = pageOrientation(newPageOrientation, currentPage.pageSize.orientation);

	if(newPageOrientation !== currentPage.pageSize.orientation) {
		return {
			orientation: newPageOrientation,
			width: currentPage.pageSize.height,
			height: currentPage.pageSize.width
		};
	} else {
		return {
			orientation: currentPage.pageSize.orientation,
			width: currentPage.pageSize.width,
			height: currentPage.pageSize.height
		};
	}

};


DocumentContext.prototype.moveToNextPage = function(pageOrientation) {
	var nextPageIndex = this.page + 1;

	var prevPage = this.page;
	var prevY = this.y;

	var createNewPage = nextPageIndex >= this.pages.length;
	if (createNewPage) {
		this.addPage(getPageSize(this.getCurrentPage(), pageOrientation));
	} else {
		this.page = nextPageIndex;
		this.initializePage();
	}

  return {
		newPageCreated: createNewPage,
		prevPage: prevPage,
		prevY: prevY,
		y: this.y
	};
};


DocumentContext.prototype.addPage = function(pageSize) {
	var page = { items: [], pageSize: pageSize };
	this.pages.push(page);
	this.page = this.pages.length - 1;
	this.initializePage();

	this.tracker.emit('pageAdded');

	return page;
};

DocumentContext.prototype.getCurrentPage = function() {
	if (this.page < 0 || this.page >= this.pages.length) return null;

	return this.pages[this.page];
};

DocumentContext.prototype.getCurrentPosition = function() {
  var pageSize = this.getCurrentPage().pageSize;
  var innerHeight = pageSize.height - this.pageMargins.top - this.pageMargins.bottom;
  var innerWidth = pageSize.width - this.pageMargins.left - this.pageMargins.right;

  return {
    pageNumber: this.page + 1,
    pageOrientation: pageSize.orientation,
    pageInnerHeight: innerHeight,
    pageInnerWidth: innerWidth,
    left: this.x,
    top: this.y,
    verticalRatio: ((this.y - this.pageMargins.top) / innerHeight),
    horizontalRatio: ((this.x - this.pageMargins.left) / innerWidth)
  };
};

function bottomMostContext(c1, c2) {
	var r;

	if (c1.page > c2.page) r = c1;
	else if (c2.page > c1.page) r = c2;
	else r = (c1.y > c2.y) ? c1 : c2;

	return {
		page: r.page,
		x: r.x,
		y: r.y,
		availableHeight: r.availableHeight,
		availableWidth: r.availableWidth
	};
}

/****TESTS**** (add a leading '/' to uncomment)
DocumentContext.bottomMostContext = bottomMostContext;
// */

module.exports = DocumentContext;
