///////////////////////////////////////////////////////////////////////////////
//
//  xamlObjects.js   			version 1.0
//  2007 Julia Yu, Lenny Burdette
//
//  These objects  have a 1 on 1 relation with a XAML file
//	And they inherit from xamlObjects
//
//  FUNCTIONS:
//			Loc.clearable
//			Loc.xamlObject
//			Loc.maps
//			Loc.textArea
//			Loc.panel
//			Loc.graphic
//			Loc.button
//			
//	DEPENDENCIES:
//			Utils.js
//			StageObjects.js
//
///////////////////////////////////////////////////////////////////////////////

if ( !window.Loc ) { window.Loc = {}; }

/**
 * Clearable is a parent class objects may extend this
 * if they contain child objects that need to be removed
 */
Loc.clearable = function() {
	this.children = {}; 						// keep track of children elements
}

Loc.clearable.prototype.addChild = function(oType, oParams) {
	if (!this.children[oType]) {
		this.children[oType] = [];				
	}
	if (!oParams.parent && this.selfContent) {
			oParams.parent = this.selfContent;						// no parent host specified, use self if it exists
	}
	if (!oParams.name) {
		oParams.name = oType + "_" + this.children[oType].length;	// make a name if no name
	}
	
	this.children[oType].push(oParams.name); 	// put child name in memory
	return Loc.make(oType, oParams); 			// make the child
}

Loc.clearable.prototype.clearChildren = function(){
	if (!this.selfContent) {
		Loc.debug("existental crises for : " + this.name); 	// no content area 
		return false;	
	}
	
	this.selfContent.children.clear(); 						// all xml nodes removed
	
	for (var childType in this.children) {
		var child = this.children[childType]; 				
		for (var z in child) {
			var childName = child[z];
			
			if (Loc.tracker[childType][childName].unload) {
				Loc.tracker[childType][childName].unload();
			}
			Loc.tracker[childType][childName] = null;
			//Loc.debug("removing: " + childType + " " + childName + " from parent: " + this.name);	
			
		}
	}
	
	this.children = {}; // set children object to nothing
}

Loc.clearable.prototype.makeNewChildren = function(parentContent, parentType, additionalParams){
	this.clearChildren();
	
	for (var contentType in parentContent) {
		var contentTypeParamsArray = parentContent[contentType]; // its an array of this contenttype
		
		for (var i in contentTypeParamsArray) {
			var contentTypeParams=contentTypeParamsArray[i];
			
			// additional parameters passed in are assigned and passed on
			if (additionalParams){
				for (var param in additionalParams) {
					contentTypeParams[param] = additionalParams[param];
				}
			}
			
			contentTypeParams.parent = this.selfContent;
			if (!contentTypeParams.name) {
				contentTypeParams.name = parentType + "_" + i + "_" + contentType; // should use name if it exists
			}
			
			this.addChild(contentType, contentTypeParams);
		}
	}
}

/**
 * Parent of stage object with their own xaml piece
 */
Loc.xamlObject = function() {
	this.host =  Loc.root; 		// the parent element where self resides
	this.self = null; 			// self is the canvas that is created
	this.selfContent = null;	// self content contains possible children
	this.top = 0;				// positions the self
	this.left = 0;
}

Loc.extend(Loc.xamlObject, Loc.clearable);

Loc.xamlObject.prototype.init = function(){} 
	
Loc.xamlObject.prototype.loaded = function(downloader, downloaderParams) {
	this.addToHost(downloader);
	//Loc.tracker.textArea[this.name].downloadPanel = null; 	
		
	if (downloaderParams.self) {
		this.self = this.fragment.findName(downloaderParams.self);
	}
	this.position(this.top, this.left);
	this.init();
}
	
Loc.xamlObject.prototype.makeDownloader = function(myXaml, mySelf) {
	this.downloadNav = new Silverlight.Downloader({
		resource : myXaml,
		plugin: Loc.plugin,
		onComplete : this.loaded.bind(this),
		name : this.name,
		self : mySelf 
	});
}
	
Loc.xamlObject.prototype.addToHost = function(downloader) {
	var xamlText = downloader.responseText; 
	this.fragment = Loc.plugin.content.createFromXaml(xamlText, true);
	this.host.children.add(this.fragment);
}
	
Loc.xamlObject.prototype.position = function(top, left) {
	var oldTop = this.self['Canvas.Top'];
	var oldLeft = this.self['Canvas.Left'];
	this.self['Canvas.Top'] = top || oldTop;
	this.self['Canvas.Left'] = left || oldLeft;
}
	
Loc.xamlObject.prototype.setSource = function(newSource) {
	if (newSource && this.selfContent) {
		this.selfContent.Source = newSource;
	}
}
	
Loc.xamlObject.prototype.show = function() {
	//Loc.debug("showing animation " + this.name);
	if (this.hideAnimation) {
		this.hideAnimation.Stop();
	}
	if (this.showAnimation) {
		this.showAnimation.Begin();
	}
}
	
Loc.xamlObject.prototype.hide = function() {
	//Loc.debug("hiding animation " + this.name);
	if (this.showAnimation) {
		try {
			this.showAnimation.Stop();
		}catch(e){}
		
	}
	if (this.hideAnimation) {
		try {
			this.hideAnimation.Begin();
		}catch(e){}
	}
}

/**
 * maps animation sequence
 */
Loc.maps = function(params) {
	this.name = params.name;
	this.host = params.parent || Loc.root;
	this.top = params.top || 0;
	this.left = params.left || 0;
	this.height = params.height || 185;
	
	this.makeDownloader("cmn/xaml/maps.xaml", "maps");
}

Loc.extend(Loc.maps, Loc.xamlObject);

Loc.maps.prototype.init = function() {
	this.show = this.fragment.findName("mapAppear");
	
	this.map1 = this.fragment.findName("map1");
	this.map2 = this.fragment.findName("map2");

	this.animateForward = this.fragment.findName("moveMaps");
	this.animateBack = this.fragment.findName("moveMaps2");
	

	
	this.map1.addEventListener('MouseLeftButtonDown', function(){ Loc.dispatch.broadcast("pageLoad", 'map1516'); });
	this.map2.addEventListener('MouseLeftButtonDown', function(){ Loc.dispatch.broadcast("pageLoad", 'map1507'); });
	
	this.animateForward.addEventListener('Completed', this.completeForward.bind(this));
	this.animateBack.addEventListener('Completed', this.completeBack.bind(this));
	
	if (this.show) {
		this.show.Begin();	
	}
	
	if (this.animateForward) {
		this.animateForward.Begin();	
	}
}

Loc.maps.prototype.completeForward = function() {	
	if (this.animateBack) {
		this.map1['Canvas.ZIndex'] = 0;
		this.map2['Canvas.ZIndex'] = 10;
		this.animateBack.Begin();
	}
}

Loc.maps.prototype.completeBack = function() {	
	if (this.animateForward) {
		this.map1['Canvas.ZIndex'] = 10;
		this.map2['Canvas.ZIndex'] = 0;
		this.animateForward.Begin();
	}
}

/**
 * The text area which paginates
 */
Loc.textArea = function(params) {
	this.name = params.name;
	this.host = params.parent || Loc.root;
	this.top = params.top || 20;
	this.left = params.left || 50;
	this.height = params.height || 185;
	this.textContent = params.content || "";
	
	this.makeDownloader("cmn/xaml/textArea.xaml", "text_box");
}

Loc.extend(Loc.textArea, Loc.xamlObject);

Loc.textArea.prototype.init = function() {
	this.content = this.fragment.findName("text_content");
	this.showAnimation = this.fragment.findName("text_appear");
	this.hideAnimation = this.fragment.findName("text_disappear");		
	
	this.formatText(this.content, this.textContent);
	this.fixHeight();
	this.initEvents();
	this.setupPagination();
	this.show();
}

Loc.textArea.prototype.fixHeight = function() {
	this.fragment.findName('text_box_bg').height = this.height;
	this.fragment.findName('text_box_clip').clip = 'M0,0 240,0 240,' + this.height + ' 0,' + this.height;
	this.fragment.findName('pagingButtons')['Canvas.Top'] = this.height + 5;
}

Loc.textArea.prototype.initEvents = function() {
	this.pageDownIcon = this.fragment.findName('pageDown');
	this.pageDownIcon.opacity = .6;
	this.pageUpIcon = this.fragment.findName('pageUp');
	this.pageUpIcon.opacity = .6;
	this.pageDownBtn = this.fragment.findName('pageDown_hit');
	this.pageDownBtn.addEventListener('MouseLeftButtonDown', this.pageDown.bind(this));
	this.pageUpBtn = this.fragment.findName('pageUp_hit');
	this.pageUpBtn.addEventListener('MouseLeftButtonDown', this.pageUp.bind(this));
	
	this.pageDownBtn.addEventListener('MouseEnter', function() {
		this.pageDownIcon.opacity = 1;
	}.bind(this));
	this.pageDownBtn.addEventListener('MouseLeave', function() {
		this.pageDownIcon.opacity = .6;
	}.bind(this));
	this.pageUpBtn.addEventListener('MouseEnter', function() {
		this.pageUpIcon.opacity = 1;
	}.bind(this));
	this.pageUpBtn.addEventListener('MouseLeave', function() {
		this.pageUpIcon.opacity = .6;
	}.bind(this));
}

Loc.textArea.prototype.setupPagination = function() {	
	this.pageSize = this.fragment.findName('text_box_bg').height;
	this.numPages = Math.ceil(this.content.actualHeight / this.pageSize * 2)-1;
	this.currentPage = 1;
	this.content['Canvas.Top'] = 0;
	this.toggleButtons();
}

Loc.textArea.prototype.pageDown = function() {
	if (this.currentPage < this.numPages) {
		this.currentPage++;
		var newTop = (this.currentPage - 1) * (-this.pageSize / 2);
		if (this.moveTween) {
			this.moveTween.stop();
		}
		this.moveTween = new Loc.Tween({ obj: this.content, prop: 'canvas.top', end: newTop, func: Loc.Tween.easeOutCubic }, 1.2).startFromHere();
		// this.content['Canvas.Top'] = (this.currentPage - 1) * (-this.pageSize / 2);
	}
	this.toggleButtons();
}

Loc.textArea.prototype.pageUp = function() {
	if (this.currentPage > 1) {
		this.currentPage--;
		var newTop = (this.currentPage - 1) * (-this.pageSize / 2);
		if (this.moveTween) {
			this.moveTween.stop();
		}
		this.moveTween = new Loc.Tween({ obj: this.content, prop: 'canvas.top', end: newTop, func: Loc.Tween.easeOutCubic }, 1.2).startFromHere();
		// this.content['Canvas.Top'] = (this.currentPage - 1) * (-this.pageSize / 2);
	}
	this.toggleButtons();
}

Loc.textArea.prototype.toggleButtons = function() {
	if (this.numPages == 1) {
		this.pageDownIcon.visibility = 'collapsed';
		this.pageUpIcon.visibility = 'collapsed';
	} 
	if (this.currentPage >= this.numPages) {
		
		this.pageDownBtn.visibility = 'collapsed';
		this.pageDownIcon.opacity = .6;
	} else {
		this.pageDownBtn.visibility = 'visible';
	}
	
	if (this.currentPage <= 1) {
		 this.pageUpBtn.visibility = 'collapsed';
		this.pageUpIcon.opacity = .6;
	} else {
		this.pageUpBtn.visibility = 'visible';
	}
}

/* OMG ITS SO UGLY */
Loc.textArea.prototype.formatText = function(block, text) {
	if (text == null) {
		Loc.debug("zOMG i have no text!!! " + this.name);
		return;
	}
	
	// no line breaks YAY
	if (text.search(/\<P\>/i) == -1) {
		block.Text = text;
		return;
	}
	
	block.text = '';
	
	try {
		while (block.inlines[0]) {
			block.inlines.removeAt(0);
		}	
	} catch(e) {}
	
	var	textPieces = text.split(/\<P\>/i),
		run = null,
		linebreak = null,
		linebreak2 = null,
		pieces;
		
	for (var i = 0, piece = null; piece = textPieces[i]; i++) {
		if (piece.search(/\<BR\>/gi) != -1) {
			pieces = piece.split(/\<BR\>/i);
			for (var j = 0, newpiece = null; newpiece = pieces[j]; j++) {
				run = Loc.plugin.content.createFromXaml('<Run/>', true);
				linebreak = Loc.plugin.content.createFromXaml('<LineBreak/>', true);
				run.text = newpiece;
				block.inlines.add(run);
				block.inlines.add(linebreak);
			}
		} else {
			run = Loc.plugin.content.createFromXaml('<Run/>', true);
			linebreak = Loc.plugin.content.createFromXaml('<LineBreak/>', true);
			linebreak2 = Loc.plugin.content.createFromXaml('<LineBreak/>', true);
			run.text = piece;
			block.inlines.add(run);
			block.inlines.add(linebreak);
			block.inlines.add(linebreak2);	
		}
	}
}

/**
 * The content panel generic object
 */
Loc.panel = function(params) {
	this.name = params.name; 	
	this.host = params.parent || Loc.root; 
	this.top = params.top || 94;
	this.left = params.left || 20;
	
	this.makeDownloader("cmn/xaml/panel.xaml", "panel");
}

Loc.extend(Loc.panel, Loc.xamlObject);

Loc.panel.prototype.init = function(params) {
	this.showAnimation = this.fragment.findName("panel_slide_out");
	this.hideAnimation = this.fragment.findName("panel_slide_in");
	this.selfContent = this.fragment.findName("panel_content");
	
	Loc.dispatch.subscribe("pageLoad", this.name, this.listenPageLoad.bind(this));
}

Loc.panel.prototype.listenPageLoad = function(pageName) {
	var myPage = Loc.page[pageName];
	if (myPage.panelContent) {
		this.makeNewChildren(myPage.panelContent, "panel");
		this.show();
	} else {
		this.clearChildren();	
		this.hide();
	}
}

/**
 * Generic image
 */
Loc.graphic = function(params) {
	this.name = params.name; 	
	this.host = params.parent || Loc.root; 		
	this.top = params.top || 0;
	this.left = params.left || 0;
	this.width = params.width || 489;
	this.height = params.height || 304;
	this.source = params.source || ""; 
	this.makeDownloader("cmn/xaml/graphic.xaml", "graphic"); 
}

Loc.extend(Loc.graphic, Loc.xamlObject);

Loc.graphic.prototype.imageLoaded = function() {
	this.preloader.stop();
	this.preloader = null;
	this.setSource(this.source); 
	this.position(this.top, this.left);
}

Loc.graphic.prototype.init = function(params) {
	this.selfContent = this.fragment.findName('myImage');
	
	var pTop = this.height/2;
	var pLeft = this.width/2-10;

	this.preloader = Loc.make('Preloader', {name: this.name+'_preloader', top: pTop, left: pLeft, parent: this.fragment });
	
	if (this.source) {
		this.downloadImage = new Silverlight.Downloader({
		    resource: this.source,
		    plugin: Loc.plugin,
		    onComplete: this.imageLoaded.bind(this),
		    name: this.name
		});
	}
}

/**
 * Generic button
 */
Loc.button = function(params) {
	this.name = params.name; 	
	this.host = params.parent || Loc.root; 		
	this.top = params.top || 0;
	this.left = params.left || 0;
	this.type = params.type || "text"; 				// can be text type or graphic type
	this.width = params.w || 100;					// hit area def
	this.height = params.h || 15;					
	this.imageSource = params.imageSource || "";
	this.margin = params.margin || 3;
	this.marginV = params.marginV || this.margin;				
	this.marginH = params.marginH || this.margin;			
	this.goToPage = params.page || "home";			// default action is to go to page
	this.buttonText = params.text || "";	
	this.click = params.click;						// click handler
	this.bgFill = params.bgFill || "gray";
	
	this.makeDownloader("cmn/xaml/button.xaml", 'button'); 
}

Loc.extend(Loc.button, Loc.xamlObject);

Loc.button.prototype.init = function(params) {
	
	this.hitArea = this.fragment.findName('button_hit');
	this.textArea = this.fragment.findName('button_text');
	this.background = this.fragment.findName('button_background');
	this.image = this.fragment.findName('button_image');
	
	this.textArea['Canvas.Top'] = this.marginV;
	this.textArea['Canvas.Left'] = this.marginH;
	
	if ((this.type == "text") && this.buttonText){
		this.textArea.Text = this.buttonText;
		this.background.fill = this.bgFill;
		this.background.visibility = "Collapsed";
		this.resizeButtonBackground();
	}
	
	if ((this.type == "image") && this.imageSource) {
		this.image.source = this.imageSource;
		this.hitArea.width = this.width;
		this.hitArea.height = this.height;
	}

	this.hitArea.addEventListener('MouseLeftButtonDown', this.buttonClick.bind(this));
	this.hitArea.addEventListener('MouseEnter', this.buttonEnter.bind(this));
	this.hitArea.addEventListener('MouseLeave', this.buttonLeave.bind(this));
}

Loc.button.prototype.changeText = function(newText) {
	if (newText) {
		this.textArea.Text = newText;
		this.resizeButtonBackground();
	}
}

Loc.button.prototype.resizeButtonBackground = function(newText) {
	this.width = this.textArea.actualWidth;
	this.height = this.textArea.actualHeight;

	this.background.width = this.width + this.marginH*2;
	this.background.height = this.height + this.marginV*2;
	
	this.hitArea.width = this.width + this.marginH*2;
	this.hitArea.height = this.height + this.marginV*2;
}

Loc.button.prototype.changeClick = function(newHandler) {
	if (typeof newHandler == "function" ){
		this.click = newHandler;
	}
}

Loc.button.prototype.buttonEnter = function() {
	if (this.type == "text"){
		this.background.visibility = "Visible";
	}
	if (this.type == "image"){
		this.image.Opacity="0.8";
	}
}

Loc.button.prototype.buttonLeave = function() {
	if (this.type == "text"){
		this.background.visibility = "Collapsed";
	}
	if (this.type == "image"){
		this.image.Opacity="1";
	}
}

Loc.button.prototype.buttonClick = function() {
	if (this.click) {
		this.click();
	} else {
		Loc.tracker.currentPage = this.goToPage;
		Loc.dispatch.broadcast("pageLoad", this.goToPage); 
	}
}