
function BaseInsert(color, alignment, size){
	try{
		this.backImage = null;
		this.init(color, alignment, size);
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.init = function(color, alignment, size) {
	this.alignment = alignment;
	if (color != null)
		this.color = color;
	else
		this.color = "black";
	this.backgroundType = "color";
	this.size = size;
	this.openingSet = new Array();
	this.timestamp = (new Date()).valueOf();
}


BaseInsert.prototype.resetTimestamp = function(){
	try{
		this.timestamp = (new Date()).valueOf();
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.resetTimestamp]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.getTimestamp = function(){
	try{
		return this.timestamp;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.getTimestamp]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.setTimestamp = function(timestamp){
	try{
		this.timestamp = timestamp;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.setTimestamp]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.toString = function (){
	try{
		var string = "(i)";
		string += this.insertID;
		string += "," + this.insertType;
		string += "," + ( this.alignment ? this.alignment : "" );
		if ( this.backgroundIsImage() )
			string += "," + ( 100 - this.maskTransparency); // ** TODO ** DeHardcode HACK
		else
			string += ",-1";
		string += "," + this.backgroundType;
		if ( this.backgroundIsColor() )
			string += "," + ( this.color ? this.color : "" );
		if ( this.backgroundIsImage() )
			string += ( this.backImage ? "," + this.backImage.toString() : "" );
		for ( var i = 0; i < this.openingSet.length; i++){
			string += this.openingSet[i].toString();
		}
		return string;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.toString]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.readInsertParam = function(string){
	try{
		string = string.replace(/\(i\)/,"");
		var insertData = string.split("(o)");
		var openings = insertData.splice(1,insertData.length);
		var insertData = insertData[0];

		insertData = insertData.split(",");

		this.insertID = insertData[0];
		this.insertType = insertData[1];
		this.alignment = insertData[2];
		if ( !Boolean(this.alignment) && this.isPano() )
			this.setEvenAlignment();
		this.maskTransparency = insertData[3];
		this.backgroundType = insertData[4];
		if ( this.backgroundIsColor() )
			this.color = insertData[5];
		if ( !this.backgroundType )
			this.removeBackgroundImage("black");
		if ( this.backgroundIsImage() ){
			this.backImage = new ImageData();
			this.backImage.readImageParam(insertData.slice(5).join(","));
		}
		if ( this.maskTransparency >= 0 && this.maskTransparency <= 100 )
			this.maskTransparency = 100 - this.maskTransparency;	// ** TODO ** DeHardcode HACK
		else
			this.maskTransparency = 30;
		//alert("Insert string: "+string+"\nthis.insertID: "+this.insertID+"\ninsertType: "+insertType+"\nthis.alignment: "+this.alignment+"\nthis.backgroundType: "+this.backgroundType+"\nthis.color: "+this.color+"\nthis.maskTransparency: "+this.maskTransparency);
		//dbg.add("<FONT color='green'><B>Reading Insert string</B>: "+string,"<I>this.insertID</I>: "+this.insertID,"<I>this.insertType</I>: "+this.insertType,"<I>this.alignment</I>: "+this.alignment,"<I>this.backgroundType</I>: "+this.backgroundType,"<I>this.color</I>: "+this.color,"<I>this.maskTransparency</I>: "+this.maskTransparency,"<I>this.backImage</I>: "+this.backImage+"<BR></FONT>");
		this.openingSet.length = 0;
		for ( var i = 0; i < openings.length; i++){
			var opening = new Opening(i);
			opening.readOpeningParam(openings[i]);
			this.addOpening(opening);
		}
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.readInsertParam]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.changeSize = function( newSize ){
	try{
		var w = newSize.width;
		var h = newSize.height;
		if ( this.isPano() )
			w = 2*w;	// This should be done on PanoInsert, instantiated by an InsertFactory.
		var size = { width: w,height: h}
		this.size = size;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.changeSize]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.getImageQuantity = function(){
	try{
		var result = 0;
		if ( this.backgroundIsImage() )
			result++;
		for ( var i = 0; i < this.openingSet.length; i++)
			if ( this.openingSet[i].hasImage() )
				result++;
		return result;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.getImageQuantity]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.assignBackgroundImage = function( image ){
	try{
		this.backImage = image;
		this.backgroundType = "image";
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.assignBackgroundImage]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.removeBackgroundImage = function( backColor ){
	try{
		this.backgroundType = "color";
		if ( backColor )
			this.color = backColor;
		var RemovedScannum = ( this.backImage ? this.backImage.getScannum() : null );
		if ( RemovedScannum ){
			this.backImage = null;
			return RemovedScannum;
		}
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.removeBackgroundImage]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.getBackgroundImage = function(){
	try{
		return this.backImage;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.getBackgroundImage]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.getMaskTransparency = function(){
	try{
		return this.maskTransparency;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.getMaskTransparency]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.setMaskTransparency = function(maskTransparency){
	try{
		this.maskTransparency = maskTransparency;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.setMaskTransparency]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.backgroundIsImage = function(){
	try{
		return this.backgroundType == "image";
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.backgroundIsImage]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.backgroundIsColor = function(){
	try{
		return this.backgroundType == "color";
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.backgroundIsColor]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.getColor = function(){
	try{
		return this.color;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.getColor]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.getAlignment = function (){
	try{
		return this.alignment;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.getAlignment]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.getHeight = function (){
	try{
		return this.size.height;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.getHeight]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.getWidth = function (){
	try{
		return this.size.width;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.getWidth]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.addOpening = function (opening){
	try{
		this.openingSet.push(opening);
		return ( this.openingSet.length - 1 );
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.addOpening]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.insertOpening = function (string){
	try{
		if (this.maxOpeningId == null) { this.maxOpeningId = this.openingSet.length; }
		var opening = new Opening(this.maxOpeningId);
		opening.readOpeningParam(string);
		this.addOpening(opening);
		this.maxOpeningId++;
		
		return (this.maxOpeningId - 1);
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.insertOpening]</B> ' + e + '</FONT>' ); return false; }
}

BaseInsert.prototype.deleteOpening = function (openingId){
	try{
		var openingPosition = this.getZIndexById(openingId);
		aTmp1 = this.openingSet.slice(0, openingPosition);
		aTmp2 = this.openingSet.slice(openingPosition + 1);
		this.openingSet = aTmp1.concat(aTmp2);
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.deleteOpening]</B> ' + e + '</FONT>' ); return false; }
}



BaseInsert.prototype.getAllZIndexes = function (){
	try{
		var openingsZIndexes = new Object();
		for ( var i = 0; i < this.openingSet.length; i++){
			openingsZIndexes[this.openingSet[i].getId()] = i;
		}
		openingsZIndexes['length'] = this.openingSet.length;
		return openingsZIndexes;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.getAllZIndexes]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.getZIndexById = function (Id){
	try{
		return (this.getAllZIndexes())[Id];
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.getZIndexById]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.getOpeningById = function (Id){
	try{
		var found = false;
		for ( var i = 0; i < this.openingSet.length && found == false; i++){
			if ( this.openingSet[i].getId() == Id )
				found = true;
		}
		return (found?(this.openingSet[i-1]):null);
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.getOpeningById]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.getOpeningByTemplateId = function (templateId){
	try{
		var found = false;
		for ( var i = 0; i < this.openingSet.length && found == false; i++){
			if ( this.openingSet[i].templateId == templateId )
				found = true; 
		}
		return (found?(this.openingSet[i-1].getId()):null);
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.getOpeningByTemplateId]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.isPano = function (){
	try{
		return (this.insertType == "pano");
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.isPano]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.isSide = function (){
	try{
		return (this.insertType == "side");
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.isSide]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.setEvenAlignment = function (){
	try{
		this.alignment = "even";
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.setEvenAlignment]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.setOddAlignment = function (){
	try{
		this.alignment = "odd";
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.setOddAlignment]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.canBeOnEven = function (){
	try{
		return !Boolean(this.alignment) || ( this.alignment == "even");
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.canBeOnEven]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.canBeOnOdd = function (){
	try{
		return !Boolean(this.alignment) || ( this.alignment == "odd");
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.canBeOnOdd]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.rotateClockWise = function (){
	try{
		if ( !this.rotation )
			this.resetRotation();
		this.rotation += 90;
		this.openingSet = this.getOpenings();
		this.resetRotation();
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.rotateClockWise]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.rotateCounterClockWise = function (){
	try{
		if ( !this.rotation )
			this.resetRotation();
		this.rotation -= 90;
		this.openingSet = this.getOpenings();
		this.resetRotation();
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.rotateCounterClockWise]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.normalizeRotation = function (){
	try{
		while ( this.rotation > 180 )
			this.rotation -= 360;
		while ( this.rotation < -90 )
			this.rotation += 360;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.normalizeRotation]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.isRotated = function (){
	try{
		if ( !this.rotation )
			return false;
		this.normalizeRotation();
		if ( this.rotation != 0)
			return true;
		return false;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.isRotated]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.getRotation = function (){
	try{
		this.normalizeRotation();
		return this.rotation;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.getRotation]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.resetRotation = function (){
	try{
		this.rotation = 0;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.resetRotation]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.bringOpeningForward = function (openingId){
	try{
		var openingPosition = this.getZIndexById(openingId);
		return ( this.openingSet.swap(openingPosition, openingPosition+1) ? (openingPosition+1) : openingPosition);
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.bringOpeningForward]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.sendOpeningBackward = function (openingId){
	try{
		var openingPosition = this.getZIndexById(openingId);
		return ( this.openingSet.swap(openingPosition, openingPosition-1) ? (openingPosition-1) : openingPosition);
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.sendOpeningBackward]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.bringOpeningtoFront = function (openingId){
	try{
		var openingPosition = this.getZIndexById(openingId);
		this.openingSet.push( this.openingSet.splice(openingPosition,1)[0] );
		return this.openingSet.length - 1;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.bringOpeningtoFront]</B> ' + e + '</FONT>' ); return false; } 
}

BaseInsert.prototype.sendOpeningtoBack = function (openingId){
	try{
		var openingPosition = this.getZIndexById(openingId);
		this.openingSet.unshift( this.openingSet.splice(openingPosition,1)[0] );
		return 0;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.sendOpeningtoBack]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.getOpenings = function (){
	try{
		if ( !this.isRotated() )
			return this.openingSet;
		return this.getRotatedOpenings();
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.getOpenings]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.getRotatedOpenings = function (){
	try{
		var rotatedOpenings = new Array();
		for ( var i = 0; i < this.openingSet.length; i++){
			rotatedOpenings.push(this.getRotatedOpening(i));
		}
		return rotatedOpenings;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.getRotatedOpenings]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.getRotatedOpening = function (position){
	try{
		// ** TODO ** Test and Decide Right Implementation
		var opening = this.openingSet[position].clone(true);
		var rotation = this.getRotation();
		if ( rotation == 90 ){
			var w = opening.getHeight();
			var h = opening.getWidth();
			var x = this.getHeight() - opening.getPositionY();
			var y = opening.getPositionX();
			opening.setHeight(h);
			opening.setWidth(w);
			opening.setPositionX(x);
			opening.setPositionY(y);
			//opening.assignRotation(opening.getRotation() + 90);
		}
		if ( rotation == 180 ){
			var x = this.getWidth() - opening.getPositionX();
			var y = this.getHeight() - opening.getPositionY();
			opening.setPositionX(x);
			opening.setPositionY(y);
			//opening.assignRotation(opening.getRotation() + 180);
		}
		if ( rotation == -90 ){
			var w = opening.getHeight();
			var h = opening.getWidth();
			var x = opening.getPositionY();
			var y = this.getWidth() - opening.getPositionX();
			opening.setHeight(h);
			opening.setWidth(w);
			opening.setPositionX(x);
			opening.setPositionY(y);
			//opening.assignRotation(opening.getRotation() - 90);
		}
		return opening;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.getRotatedOpening]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.getOpening = function (position){
	try{
		if ( !this.isRotated() )
			return this.openingSet[position];
		return this.getRotatedOpening(position);
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.getOpening]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.replaceOpening = function (opening, position){
	try{
		if ( position == null )
			position = this.openingSet.length - 1;
		this.openingSet.splice(position,1,opening);
		return position;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.replaceOpening]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.getType = function (){
	try{
		return this.type;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.getType]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.getTemplateID = function (){
	try{	
		return this.insertID;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.getTemplateId]</B> ' + e + '</FONT>' ); return false; } 
}


BaseInsert.prototype.hasBorder = function (borderId){
	try{	
		for ( var i = 0; i < this.openingSet.length; i++) 
			if (this.openingSet[i].getBorderType() == borderId) 
				return true;
		return false;
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[BaseInsert.hasBorder]</B> ' + e + '</FONT>' ); return false; } 

}


							/*********  SideInsert *********/

SideInsert.prototype = new BaseInsert;
SideInsert.prototype.constructor = SideInsert;
SideInsert.superclass = BaseInsert.prototype;

function SideInsert(color, alignment, size){
	try
	{
		this.init(color, alignment, size);
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[SideInsert]</B> ' + e + '</FONT>' ); return false; } 
}


							/*********  PanoInsert *********/

PanoInsert.prototype = new BaseInsert;
PanoInsert.prototype.constructor = PanoInsert;
PanoInsert.superclass = BaseInsert.prototype;

function PanoInsert(color, alignment, size){
	try{
		this.init(color, "even", size);
		this.insertType = "pano";
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[PanoInsert]</B> ' + e + '</FONT>' ); return false; } 
}

PanoInsert.prototype.changeSize = function( albumSize ){
	try{
		alert("[PanoInsert.changeSize] unexpected Code executed"); // ** TODO ** remove after definitions are settled
		this.size = {width: 2*albumSize.width, height: albumSize.height};
	}
	catch(e){ dbg.add ( '<FONT COLOR="red"><B>[PanoInsert.changeSize]</B> ' + e + '</FONT>' ); return false; } 
}


