// Pricing Calculation script
// Copyright 2005-2012 © Printing-Online.com.au Pty Ltd 

// Enumerations
var ProofOption = new Object();
ProofOption.PDF = 1;
ProofOption.HardCopy = 2;
ProofOption.NoProof = 3;

var PrintMethod = new Object();
PrintMethod.Digital = 1;
PrintMethod.Offset = 2;

var FoldingOption = new Object();
FoldingOption.None = 1;
FoldingOption.HalfFold = 2;
FoldingOption.ZFold = 4;
FoldingOption.TriFold = 8;

var FoldingChoice = new Object();
FoldingChoice.None = 1;
FoldingChoice.NoneAndHalfFold = 3;
FoldingChoice.NoneZFoldTriFold = 13;
FoldingChoice.NoneHalfZFoldTriFold = 15;

var FileTransferMethod = new Object();
FileTransferMethod.Email = 1;
FileTransferMethod.Upload = 2;
FileTransferMethod.SnailMail = 3;
FileTransferMethod.ReprintExact = 4;
FileTransferMethod.ReprintWithChanges = 5;
FileTransferMethod.DesignOnline = 6;

var DeliveryMethod = new Object();
DeliveryMethod.AustraliaEconomy = 1;
DeliveryMethod.AustraliaPremium = 2;
DeliveryMethod.AustraliaAusPost = 4;
DeliveryMethod.International = 3;

var ColourOption = new Object();
ColourOption.FullColour = 1;
ColourOption.BlackAndWhite = 2;
ColourOption.Blank = 4;

var ColourChoice = new Object();
ColourChoice.Colour = 1;
ColourChoice.BlackWhite = 2;
ColourChoice.ColourAndBlackWhite = 3;
ColourChoice.Blank = 4;
ColourChoice.ColourAndBlank = 5;
ColourChoice.BlackWhiteAndBlank = 6;
ColourChoice.ColourAndBlackWhiteAndBlank = 7;

var ArtworkType = new Object();
ArtworkType.Unknown = 0;
ArtworkType.DesignOnline = 1;
ArtworkType.UploadOther = 2;
ArtworkType.AlreadyDesignedOnline = 3;
ArtworkType.ReprintJobExact = 4;
ArtworkType.ReprintJobWithChanges = 5;

var EnvelopeWindowOption = new Object();
EnvelopeWindowOption.None = 1;
EnvelopeWindowOption.Plain = 2;
EnvelopeWindowOption.Window = 4;
	
var EnvelopeWindowChoice = new Object();
EnvelopeWindowChoice.None = 1;
EnvelopeWindowChoice.PlainOrWindow = 6;

var DOCKETPERFORATION_ALL = "ALL pages";

var m_Data = new Object();

var m_ProductId;
var m_QuantityString;
var m_Quantity;
var m_DesignCount = 1;
var m_TotalQuantity;
var m_FrontColourId;
var m_BackColourId;
var m_PaperTypeId;
var m_FoldingOption;
var m_EnvelopeWindowOption;
var m_DeliveryMethod;
var m_CountryId;
var m_PostCodeString;
var m_ProductionSpeed;
var m_ProofOption;
var m_PageCountString;
var m_ArtworkType = 0;
var m_PageCount = 0;
var m_HasFridgeMagnet = 0;
var m_HasDrilledHole = 0;
var m_PerforationType = "";

var m_PrintingMethod = PrintMethod.Digital;
var m_BasePrice = 0;
var m_BasePriceWithProf = 0;
var m_PaperSheetsNeeded = 0;
var m_PaperPrice = 0;
var m_TrimmingPrice = 0;
var m_FoldingPrice = 0;
var m_FreightPrice = 0;

var m_BaseProfRow;
var m_NextProfRow;
var m_PaperTypeRow = null;


function InitCalculator(productId, quantityString, frontColourId, backColourId, paperTypeId,
	foldingOption, deliveryMethodRaw, countryId, postCodeString,
	productionSpeed, proofOption, pageCountString, artworkType, designCount, envWindowOption, 
	hasFridgeMagnet, hasDrilledHole, perforationType)
{
	m_ProductId = productId;
	m_QuantityString = quantityString;
	m_DesignCount = parseInt(designCount, 10);
			
	m_FrontColourId = parseInt(frontColourId, 10);
	m_BackColourId = parseInt(backColourId, 10);
	m_PaperTypeId = paperTypeId;
	m_FoldingOption = parseInt(foldingOption, 10);
	m_EnvelopeWindowOption = parseInt(envWindowOption, 10);
	m_DeliveryMethod = parseInt(deliveryMethodRaw, 10);
	m_CountryId = countryId;
	m_PostCodeString = postCodeString;
	m_ProductionSpeed = parseInt(productionSpeed, 10);
	m_ProofOption = parseInt(proofOption, 10);
	m_PageCountString = pageCountString;
	m_ArtworkType = parseInt(artworkType, 10);
	m_PageCount = parseInt(m_PageCountString, 10);
	m_HasFridgeMagnet = hasFridgeMagnet; 
    m_HasDrilledHole = hasDrilledHole;
    m_PerforationType = perforationType;
    
	m_PrintingMethod = PrintMethod.Digital;
	m_BasePrice = 0;
	m_BasePriceWithProf = 0;
	m_PaperSheetsNeeded = 0;
	m_PaperPrice = 0;
	m_TrimmingPrice = 0;
	m_FoldingPrice = 0;
	m_FreightPrice = 0;
	m_BaseProfRow = null;
	m_NextProfRow = null;
	m_PaperTypeRow = null;
	
	m_Data.SubTotal = 0;
	m_Data.Admin = 0;
	m_Data.Proof = 0;
	m_Data.Urgency = 0;
	m_Data.Freight = 0;
	m_Data.Total = 0;
	m_Data.CostPerUnit = 0;
	m_Data.Commission = 0;	
	m_Data.Discount
}


function Calculate()
{
	m_Quantity = parseInt(m_QuantityString, 10);
		
	if (isNaN(m_Quantity))
	{
		return m_Data;
	}
	if (m_Quantity < 1 || m_Quantity > m_ProductRow.QuantityMax)
	{
		return m_Data;
	}
	m_TotalQuantity = m_Quantity * m_DesignCount;

	m_ProductRow = GetProductRow(m_ProductId);

	m_PaperTypeRow = GetPaperTypeRow(m_PaperTypeId);

	var urgencyPrice = 0;
	var proofPrice = 0;

	if (m_ProofOption == ProofOption.HardCopy)
	{
		proofPrice = m_ProductRow.ProofCost;
	}

	CalculateSubTotal();
	
	CalculateFridgeMagnetPrice();

	CalculateDrilledHolePrice();

	m_Data.SubTotal = RoundToTwoDecimals(m_Data.SubTotal);

	urgencyPrice = CalculateUrgency();

	CalculateFreight();
	m_Data.Freight = m_FreightPrice;
	
	switch (m_ArtworkType)
	{
		case ArtworkType.ReprintJobExact:
		case ArtworkType.DesignOnline:
		case ArtworkType.AlreadyDesignedOnline:
			m_Data.Admin = 0;
			break;

		default:
			m_Data.Admin = m_ProductRow.AdminCost * m_DesignCount;	
			break;
	}

	m_Data.Proof = RoundToTwoDecimals(proofPrice);
	m_Data.Urgency = RoundToTwoDecimals(urgencyPrice);

	m_Data.SubTotal += m_Data.SubTotal * Settings.SiteMarkupPercent;
	m_Data.Urgency += m_Data.Urgency * Settings.SiteMarkupPercent;
	m_Data.Proof += m_Data.Proof * Settings.SiteMarkupPercent;
	m_Data.Admin += m_Data.Admin * Settings.SiteMarkupPercent;

	m_Data.Commission = 0;
	
	m_Data.Total = (m_Data.SubTotal + m_Data.Proof + m_Data.Urgency + m_Data.Admin);
	m_Data.DiscountPrice = m_ProductRow.DiscountAmount;
	
	if (m_ProductRow.DiscountPercent > 0)
	{
		m_Data.DiscountPrice += m_Data.Total * (m_ProductRow.DiscountPercent/100.0);
	}
	m_Data.Total = RoundToTwoDecimals(m_Data.Total - m_Data.DiscountPrice + m_Data.Freight);
	

	if (m_TotalQuantity > 0)
	{
		m_Data.CostPerUnit = m_Data.Total / m_TotalQuantity;
	}

	return m_Data;
}

// Product switching
function CalculateSubTotal()
{
	if (m_ProductRow.ProductTypeID == "S")
		CalculateSubTotalForStandard();
	else
		CalculateSubTotalForDiscount();
	
	// Also applies to discount products
	var windowedEnvelopeCost = CalculateEnvelopeWindowCost(m_TotalQuantity);
	m_Data.SubTotal += windowedEnvelopeCost;
}

function CalculatePM(quantity)
{
	if (m_ProductRow.ProductTypeID == "S")
		CalculatePMForStandard(quantity);
	else
		CalculatePMForDiscount(quantity);
}

function CalculateFoldingCost(quantity)
{
	if (m_ProductRow.ProductTypeID == "S")
		CalculateFoldingCostForStandard(quantity);
	else
		CalculateFoldingCostForDiscount(quantity);
}

function CalculateEnvelopeWindowCost(quantity)
{
	var envWindowPrice = 0;
	if (m_EnvelopeWindowOption == EnvelopeWindowOption.Window)
	{
		// Windowed envelopes cost $15 per 1000 or part of
		var mill = Math.floor( quantity / 1000 );
		mill += 1;
		envWindowPrice = mill * 15;
	}
	return envWindowPrice;
}

function CalculateSubTotalForQuantity(quantity)
{
	CalculatePaperSheetsNeeded(quantity);

	m_PaperPrice = m_PaperSheetsNeeded * m_PaperTypeRow.PaperCost;

	if (quantity > m_ProductRow.DigitalMaxCopies)
	{
		m_PrintingMethod = PrintMethod.Offset;
	}

	var printMethodRow = GetPrintMethodRow(m_PrintingMethod);
	var frontPagePrice = m_PaperSheetsNeeded * printMethodRow.ColourCost;

	var backColour = m_BackColourId;
	var backColourPerPageCost = printMethodRow.ColourCost;
	switch (backColour)
	{
		case ColourOption.FullColour:
			backColourPerPageCost = printMethodRow.ColourCost;
			break;
		case ColourOption.BlackAndWhite:
			backColourPerPageCost = printMethodRow.BlackWhiteCost;
			break;
		case ColourOption.Blank:
			backColourPerPageCost = printMethodRow.BlankCost;
			break;
	}
	var backPagePrice = m_PaperSheetsNeeded * backColourPerPageCost;
	
	m_BasePrice = m_PaperPrice + frontPagePrice + backPagePrice + printMethodRow.SetupCost;

	CalculatePM(quantity);
	CalculateTrimmingCost();
	CalculateFoldingCost(quantity);

	return m_BasePriceWithProf + m_TrimmingPrice + m_FoldingPrice;
}

function CalculateTrimmingCost()
{
	if (m_ProductRow.ProductTypeID == "S")
		CalculateTrimmingCostForStandard();
	else
		CalculateTrimmingCostForDiscount();
}

function CalculateUrgency()
{
	var urgencyPrice = 0;
	var productionSpeedRow = GetProductionSpeedRow(m_ProductionSpeed);
	urgencyPrice = m_Data.SubTotal * productionSpeedRow.SurchargePercent;
	return urgencyPrice;
}

function CalculateFridgeMagnetPrice()
{
	if (!m_HasFridgeMagnet) { return; }

	var pricePerItem = 0;

	//for (var i = 0;i < MagnetPriceList.length; i++)
	for (var i in MagnetPriceList)
	{
		//var currentRow = MagnetPriceList[i];
		//alert(MagnetPriceList[i]);
		if (m_TotalQuantity >= MagnetPriceList[i].Quantity)
		{
			pricePerItem = MagnetPriceList[i].Price;
		}
	}

	var magnetPrice = m_TotalQuantity * pricePerItem;
	if (magnetPrice < Settings.FridgeMagnetsMinimumCost)
	{
		magnetPrice = Settings.FridgeMagnetsMinimumCost;
	}

	m_Data.SubTotal += magnetPrice;
}


function CalculateDrilledHolePrice()
{
	if (!m_HasDrilledHole) { return; }

	var qtyThousands = Math.ceil(m_TotalQuantity / 1000);
	var drilledHolePrice = qtyThousands * Settings.DrilledHolesCostPerThousand;
	if (drilledHolePrice < Settings.DrilledHolesMinimumCost)
	{
		drilledHolePrice = Settings.DrilledHolesMinimumCost;
	}
	m_Data.SubTotal += drilledHolePrice;
}

function CalculatePaperSheetsNeeded(quantity)
{
	m_PaperSheetsNeeded = Math.ceil(quantity / m_ProductRow.NumberPerA3);
	if (m_PageCount > 1) // Docketbooks
	{
		m_PaperSheetsNeeded = m_PaperSheetsNeeded * (m_PageCount / 4);
	}

	if (m_PaperSheetsNeeded <= 0)
	{
		m_PaperSheetsNeeded = 1;
	}
}

function CalculateFoldingCostForStandard(quantity)
{
	if (m_FoldingOption != FoldingOption.None)
	{
		var foldingRow = GetFoldingCostRow(quantity);
		m_FoldingPrice = foldingRow.FoldingCost;
	}
}

function CalculateTrimmingCostForStandard()
{
	var trimCostRow = GetTrimCostRow(m_PaperSheetsNeeded);
	m_TrimmingPrice = trimCostRow.TrimCost;
}

function CalculatePMForStandard(quantity)
{
	var profRow = GetPMRow(quantity);
	m_BasePriceWithProf = m_BasePrice / (1 - profRow.pmPercent);
}

function CalculateFreight()
{
	CalculatePaperSheetsNeeded(m_TotalQuantity);

	var paperWeightRow = GetPaperWeightRow(m_PaperTypeRow.GSM);
	var freightWeightGrams = m_PaperSheetsNeeded * paperWeightRow.GramsPerA3;

	switch (m_DeliveryMethod)
	{
		case DeliveryMethod.International:

			var intZoneRow = GetFreightZoneInternationalRow(m_CountryId);
			if (isNull(intZoneRow))
			{
				m_FreightPrice = 0;
				break;
			}

			if (freightWeightGrams <= 250)
			{
				m_FreightPrice = intZoneRow.LessThan250g;
			}
			else if (freightWeightGrams > 250 && freightWeightGrams <= 500)
			{
				m_FreightPrice = intZoneRow.Between250and500g;
			}
			else if (freightWeightGrams > 500 && freightWeightGrams <= 1000)
			{
				m_FreightPrice = intZoneRow.Between500and1000g;
			}
			else // > 1kg
			{
				m_FreightPrice = intZoneRow.Between500and1000g;
				var partKilos = Math.ceil((freightWeightGrams-1000.0)/1000.0);
				m_FreightPrice += partKilos * intZoneRow.PartKiloThereafter;
			}
			break;

		case DeliveryMethod.AustraliaEconomy:
		case DeliveryMethod.AustraliaPremium:
		case DeliveryMethod.AustraliaAusPost:
			var postCode = 0;
			var freight250gramUnits = 0;
			postCode = parseInt(m_PostCodeString, 10);

			if (!isNaN(postCode) && postCode > 0)
			{
				var freightZoneRow = GetFreightZoneAustRow(postCode);

				if (isNull(freightZoneRow))
				{
					//data.IsPostcodeValid = false;
				}
				else
				{
					freight250gramUnits = Math.ceil(freightWeightGrams / 250);

					m_FreightPrice = freightZoneRow.BasicCost + (freightZoneRow.CostPer250Grams * freight250gramUnits);

					if (m_DeliveryMethod == DeliveryMethod.AustraliaPremium)
					{
						m_FreightPrice *= freightZoneRow.prem;
					}
					else if (m_DeliveryMethod == DeliveryMethod.AustraliaAusPost)
					{
						m_FreightPrice *= Settings.AusPostMultiplier;
					}
				}
			}
			break;
	}
}

function RoundToTwoDecimals(value)
{
	return Math.round(value * 100) / 100;
}

function IsPostcodeValid(postCodeString)
{
	var postCode = 0;

	postCode = parseInt(postCodeString, 10);
	if (isNaN(postCodeString))
	{
		return false;
	}
	var freightZoneRow = GetFreightZoneAustRow(postCode);

	if (isNull(freightZoneRow))
	{
		return false;
	}
	else
	{
		return true;
	}
}
// End simple calc

function CalculateSubTotalForStandard()
{
	GetPMRows(m_TotalQuantity);

	var basePrice = CalculateSubTotalForQuantity(m_BaseProfRow.ItemCount);

	if (m_TotalQuantity == m_BaseProfRow.ItemCount)
	{
		m_Data.SubTotal = basePrice;
	}
	else if (isNull(m_NextProfRow))
	{
		m_Data.SubTotal = CalculateSubTotalForQuantity(m_TotalQuantity);
	}
	else
	{
		var nextPrice = CalculateSubTotalForQuantity(m_NextProfRow.ItemCount);

		var quantityRange = m_NextProfRow.ItemCount - m_BaseProfRow.ItemCount;
		var priceRange = nextPrice - basePrice;

		var quantityDiff = m_TotalQuantity - m_BaseProfRow.ItemCount;

		var percentDiff = quantityDiff / quantityRange;

		m_Data.SubTotal = basePrice + (percentDiff * priceRange);
	}
}
// End Standard


// Discount
function CalculateSubTotalForDiscount()
{
	m_Data.SubTotal = CalculateSubTotalForQuantity(m_TotalQuantity);

	m_BasePriceWithProf = GetBulkPrice(m_Quantity, m_FrontColourId, m_BackColourId, m_PaperTypeId, m_PageCount);
	m_BasePriceWithProf = m_BasePriceWithProf * m_DesignCount;	
	
	// Docket books with all pages perforated
	var perforationCost = 0;

	if (m_PerforationType == DOCKETPERFORATION_ALL)
	{
		// $15 setup and $1.50 per book
		perforationCost = 15 + (1.5 * m_Quantity);
	}
	
	m_BasePrice = m_BasePriceWithProf + perforationCost;
	m_Data.SubTotal = m_BasePrice;
}

function CalculateTrimmingCostForDiscount()
{
	m_TrimmingPrice = 0;
}

function CalculatePMForDiscount(quantity)
{
	m_BasePriceWithProf = m_BasePrice;
}

function CalculateFoldingCostForDiscount(quantity)
{
	m_FoldingPrice = 0;
}

// Data retrieval
function GetBulkPrice(quantity, frontColourOptionId, backColourOptionId, paperTypeId, pageCount)
{
	var bulkRow = BulkPriceList[quantity + ":" + frontColourOptionId + ":" + backColourOptionId + ":" + paperTypeId + ":" + pageCount];
	return bulkRow.Price;
}

function GetFoldingCostRow(quantity)
{
	var previousRow = null;

	var index = 0;
	for (var key in FoldingCostList)
	{
		var currentRow = FoldingCostList[key];
		if (index == 0) { previousRow = currentRow; }
		
		if (previousRow.ItemCount <= quantity && currentRow.ItemCount > quantity)
		{
			return previousRow;
		}
		previousRow = currentRow;
		index += 1;
	}

	return previousRow;
}

function GetFreightZoneInternationalRow(countryId)
{
	var countryRow = fcList[countryId];

	if (isNull(countryRow))
		{ return null; }

	return fziList[countryRow.fziID];
}

function GetFreightZoneAustRow(postCode)
{
	var postCodeRow = null;

	for (var key in fpcList)
	{
		var currentRow = fpcList[key];
		if (currentRow.pc1 <= postCode && currentRow.pc2 >= postCode)
		{
			postCodeRow	= currentRow;
			break;
		}
	}

	if (isNull(postCodeRow))
	{
		return null;
	}

	return fzaList[postCodeRow.ZoneID];
}

function GetPaperTypeRow(paperTypeId)
{
	return PaperTypeList[paperTypeId];
}

function GetPaperWeightRow(gsm)
{
	return PaperWeightList[gsm];
}

function GetPrintMethodRow(printMethodId)
{
	return PrintMethodList[printMethodId];
}

function GetProductRow(productId)
{
	return m_ProductRow;
}

function GetProductionSpeedRow(productionSpeedId)
{
	return ProductionSpeedList[productionSpeedId];
}

function GetPMRows(quantity)
{
	m_BaseProfRow = null;
	m_NextProfRow = null;

	var previousRow = null;

	var index = 0;
	var currentRow;
	for (var key in pmList)
	{
		currentRow = pmList[key];
		if (index == 0) { previousRow = currentRow; }

		if (previousRow.ItemCount <= quantity && currentRow.ItemCount > quantity)
		{
			m_BaseProfRow = previousRow;
			m_NextProfRow = currentRow;
			break;
		}
		previousRow = currentRow;
		index += 1;
	}

	if (isNull(m_BaseProfRow))
	{
		m_BaseProfRow = currentRow;
	}
}

function GetPMRow(quantity)
{
	var previousRow = null;

	var index = 0;
	for (var key in pmList)
	{
		var currentRow = pmList[key];
		if (index == 0) { previousRow = currentRow; }

		if (previousRow.ItemCount <= quantity && currentRow.ItemCount > quantity)
		{
			return previousRow;
		}
		previousRow = currentRow;
		index += 1;
	}

	return previousRow;
}

function GetTrimCostRow(quantity)
{
	var previousRow = null;

	var index = 0;
	for (var key in TrimCostList)
	{
		var currentRow = TrimCostList[key];
		if (index == 0) { previousRow = currentRow; }

		if (previousRow.A3SheetCount <= quantity && currentRow.A3SheetCount > quantity)
		{
			return previousRow;
		}
		previousRow = currentRow;
		index += 1;
	}

	return previousRow;
}

function isNull(variable)
{
	// null or undefined evaluates as false
	// assigned variables evaluate as true
	return (!variable);
}
