/**

Note to self:
	as of 2008/11/01, flash 10, setting display:none or visibility: hidden kills Flash's ExternalInterface
		(at least under windows FF). Current workaround is to move them off-screen since they are pos=absolute

*/

document.domain = 'nomadnation.tv';

if (!window['jQuery'])
	alert('nmtv.js missing jQuery!');

var nmtv; // global scope

try {
    if (window.parent && window.parent['nmtv'])
        nmtv = window.parent.nmtv;
} catch (securityErrorInIE) {
    alert(securityErrorInIE);
    // do nothing
}

if (!nmtv) { // until EOF

Namespace = function(name, parent)
{
	this.name = name;
	this.parent = parent;
}
Namespace.prototype.getQualifiedName = function()
{
	return (this.parent?(this.parent.getQualifiedName()+'.'):'') + this.name;
}
Namespace.prototype.toString = function()
{
	return '[namespace ' + this.getQualifiedName() + ']';
}

window['nmtv'] = nmtv = new Namespace('nmtv');

nmtv.DEBUG = 0;

nmtv.inherit = function(instance, protoFunction)
{
	var args = [];
	for (var i = 2; i < arguments.length; ++i)
		args.push(arguments[i]);
	protoFunction.apply(instance, args);
}

nmtv.ensureArray = function(maybeArray)
{
	if (maybeArray == null)
		return null;
	if (typeof(maybeArray['length']) != "number")
		return [maybeArray];
	var array = new Array(maybeArray.length);
	for (var i = 0; i < array.length; ++i)
		array[i] = maybeArray[i];
	return array;
}

nmtv.Namespace = Namespace;
nmtv.events = new nmtv.Namespace('events', nmtv);


nmtv.events.Event = function(type, props)
{
	if (!type)
		throw new Error('event must have a type');
	this.type = type;
	if (props)
	for (var i in props)
		this[i] = props[i];
}
nmtv.events.Event.prototype.toString = function()
{
	return '[object nmtv.events.Event; type='+this.type+']';
}
nmtv.events.Event.READY = 'nmtv.ready';
nmtv.events.Event.SECTION_LOAD = 'nmtv.section_load';
nmtv.events.Event.SECTION_CHANGE = 'nmtv.section_change';
nmtv.events.Event.SECTION_URL_CHANGE = 'nmtv.section_url_change';

nmtv.events.EventListener = function(closure, context, args)
{
	this.closure = closure;
	this.context = context;
	this.args = nmtv.ensureArray(args) || [];
}
/**
@param arguments arguments pre-pended to the final list of arguments; its not clear which is better pre or post-pend these args
*/
nmtv.events.EventListener.wrap = function(closure, context, args)
{
	if (closure instanceof nmtv.events.EventListener)
		return closure;
	return new nmtv.events.EventListener(closure, context, args);
}
nmtv.events.EventListener.prototype.toString = function()
{
	return '[object nmtv.events.EventListener; context=' + this.context + '; closure=' + this.closure + '; args=' + this.args + ']';
}
nmtv.events.EventListener.prototype.apply = function()
{
try {
	var args = this.args.concat();
	// arguments[1] = context (ignored);
	if (arguments.length > 1)
		for (var i = 0; i < arguments[1].length; ++i)
			args.push(arguments[1][i]);
	this.closure.apply(this.context, args);
} catch (e) {
	alert(e);
}
}

nmtv.events.EventDispatcher = function()
{
	this.listeners = {};
}
nmtv.events.EventDispatcher.prototype.toString = function()
{
	return '[object nmtv.events.EventDispatcher]';
}
nmtv.events.EventDispatcher.prototype.getListeners = function(type)
{
	if (!this.listeners[type])
		this.listeners[type] = [];
	return this.listeners[type];
}
nmtv.events.EventDispatcher.prototype.addEventListener = function(type, listener, context)
{
	listener = nmtv.events.EventListener.wrap(listener, context);
	this.getListeners(type).push(listener);
}
nmtv.events.EventDispatcher.prototype.removeEventListener = function(type, listener, context)
{
	var listeners = this.getListeners(type);
	for (var i = 0; i < listeners.length; ++i)
	{
        var l = listeners[i];
		if (l == listener || (l.closure == listener && l.context == context)) {
			listeners.splice(i, 1);
			break;
		}
	}
}
nmtv.events.EventDispatcher.prototype.hasEventListener = function(type)
{
	return this.getListeners(type).length > 0;
}
nmtv.events.EventDispatcher.prototype.dispatchEvent = function(event)
{
	var listeners = this.getListeners(event.type);

	for (var i in listeners)
	{
		var listener = listeners[i];
		listener.apply(null, arguments);
	}
}


/**
Class for handling url hashes as deep links

@param hash either a string literal hash or window object from which to populate or null
*/
nmtv.Hash = function(hashstr)
{
	this.props = {};
	if (!hashstr)
		return;
	if (typeof(hashstr) == 'object') {
		if (hashstr.location) // assume window
			hashstr = hashstr.location.hash;
		else {
			for (var i in hashstr) {
				if (!i) // ?
					continue;
				this.props[i] = hashstr[i];
			}
			return;
		}
	}
	var hash = hashstr.split('/');
	while (hash.length && (hash[0]=='#' || !hash[0].length))
		hash.shift();
	for (var i in hash) {
		if (!i)
			continue;
		pieces = hash[i].split(',');
		var name = pieces.shift();
		this.props[name] = pieces;
	}
}
nmtv.Hash.prototype.has = function(name)
{
	return this.props.hasOwnProperty(name);
}
nmtv.Hash.prototype.set = function(name, value)
{
	this.props[name] = value;
}
nmtv.Hash.prototype.get = function(name)
{
	return this.props[name];
}
nmtv.Hash.prototype.toString = function()
{
	var bits = [];
	for (var i in this.props) {
		if (this.props[i] === null || this.props[i] === undefined)
			continue;
		bits.push(i + ',' + this.props[i]);
	}
	return '/'+bits.join('/');
}

/**
*/
nmtv.Site = function()
{
	nmtv.inherit(this, nmtv.events.EventDispatcher);
//	this.ids = {};
//	this.ids[nmtv.Site.MAP] = mapId;
//	this.ids[nmtv.Site.BLOG] = blogId;
	this.blog = null;
	this.map = null;
	this.book = null;
//	this.activeSection = null;
	this.activeSectionId = null;
	this.isLoadingSection = false;
	this.isReady = false;
	this.isTransitioning = false;
    this.sectionTransitionsEnabled = true;
	this.isFirstTransition = true;
	this.sectionInfo = {};
	this.sectionInfo[nmtv.Section.BLOG] = new nmtv.SectionInfo(nmtv.Section.BLOG);
	this.sectionInfo[nmtv.Section.BOOK] = new nmtv.SectionInfo(nmtv.Section.BOOK);
	this.sectionInfo[nmtv.Section.MAP] = new nmtv.SectionInfo(nmtv.Section.MAP);
	this.sections = {};
	this.win = window;
	
}
nmtv.Site.ARROW_DOWN = '&#x21e3;';
nmtv.Site.ARROW_UP = '&#x21e1;';
nmtv.Site.OPEN_TIME = 500;
nmtv.Site.CLOSE_TIME = 500;
nmtv.Site.EASE_CLOSE = 'easeOutQuad';
nmtv.Site.EASE_OPEN = 'easeOutQuad';

nmtv.Site.prototype = new nmtv.events.EventDispatcher();

nmtv.Site.prototype.toString = function()
{
	return '[object nmtv.Site]';
}
nmtv.Site.prototype.getActiveSectionId = function()
{
	return this.activeSectionId;
}
nmtv.Site.prototype.getActiveSection = function()
{
	if (this.activeSectionId !== null)
		return this.sections[this.activeSectionId];
	return null;
}
nmtv.Site.prototype.getActiveSectionInfo = function()
{
	if (this.activeSectionId !== null)
		return this.sectionInfo[this.activeSectionId];
	return null;
}
nmtv.Site.prototype.setSection = function(name, child)
{
	var wasReady = this.blog && this.map && this.book;
    var old = null;
	if (this.sections[name]) {
		old = this.sections[name];
		//alert('old='+old.hasEventListener(nmtv.events.Event.SECTION_URL_CHANGE));
		old.removeEventListener(nmtv.events.Event.SECTION_URL_CHANGE, this.onSectionUrlChange, this);
	}

	this.sections[name] = child;
	this.sectionInfo[name].section = child;
	switch (name)
	{
	case nmtv.Section.BLOG:
		this.blog = child;
		break;
	case nmtv.Section.MAP:
		this.map = child;
		break;
	case nmtv.Section.BOOK:
		this.book = child;
		break;
	}
	
    if (!old)
        child.updateHash(this.calculateHash());
	
	child.addEventListener(nmtv.events.Event.SECTION_URL_CHANGE, this.onSectionUrlChange, this);
	this.dispatchEvent(new nmtv.events.Event(nmtv.events.Event.SECTION_LOAD, {section:child}));
	var isReady = this.blog && this.map && this.book;
	if (!wasReady && isReady) {
		var This = this;
		// why a new thread?
		setTimeout(function() {
			This.isReady = true;
			This.dispatchEvent(new nmtv.events.Event(nmtv.events.Event.READY));
		}, 1);
	}
}
nmtv.Site.prototype.navigateToMoment = function(momentid)
{
	/* abstract */
	return false;
}
nmtv.Site.prototype.hideBorders = function()
{
//	$('#topSlide, #bottomSlide').css({borderType: 'none', display: 'none'});
}
nmtv.Site.prototype.showBorders = function()
{
//	$('#topSlide, #bottomSlide').css({borderType: 'solid', display: 'block'});
}
nmtv.Site.prototype.close = function(which, callback, animate)
{
	if (animate === null) animate = true;
	animate = true;
	$('#'+which).css({bottom:'auto',top:'45px'});
    if (this.sectionTransitionsEnabled && animate) {
        $('#'+which).animate({top: '100%'}, {easing: nmtv.Site.EASE_CLOSE, duration: nmtv.Site.CLOSE_TIME, complete: callback});
	} else {
		$('#'+which).css({top: '100%'});
        if (callback) callback();
    }
//	this.showBorders();
//	$('#topSlide').find('.left,.right').html(nmtv.Site.ARROW_DOWN);
//	$('#bottomSlide').find('.left,.right').html(nmtv.Site.ARROW_UP);
//	$('#topSlide').animate({height: '50%'}, {easing: nmtv.Site.EASE_CLOSE, duration: nmtv.Site.CLOSE_TIME-1, complete: this.hideBorders});
//	$('#bottomSlide').animate({height: '50%'}, {easing: nmtv.Site.EASE_CLOSE, duration: nmtv.Site.CLOSE_TIME, complete: callback});
}
nmtv.Site.prototype.open = function(which, callback, animate)
{
	if (animate === null) animate = true;
	$('#'+which).css({top:'auto',bottom:'100%'});
    if (this.sectionTransitionsEnabled && animate) {
        $('#'+which).animate({bottom: '45px'}, {easing: nmtv.Site.EASE_OPEN, duration: nmtv.Site.OPEN_TIME, complete: callback});
	} else {
        $('#'+which).css({bottom: '45px'});
        if (callback) callback();
    }
//	$('#'+which).css({top: '0%'});
//	this.showBorders();
//	$('#topSlide').find('.left,.right').html(nmtv.Site.ARROW_UP);
//	$('#bottomSlide').find('.left,.right').html(nmtv.Site.ARROW_DOWN);
//	$('#topSlide').animate({height: '0%'}, {easing: nmtv.Site.EASE_OPEN, duration: nmtv.Site.OPEN_TIME-1, complete: this.hideBorders});
//	$('#bottomSlide').animate({height: '0%'}, {easing: nmtv.Site.EASE_OPEN, duration: nmtv.Site.OPEN_TIME, complete: callback});
}
nmtv.Site.prototype.hideActiveSection = function(callback)
{
	try{
	var id = this.activeSectionId;
	if (!id)
		return;
	if (this.sectionInfo[id].section)
		this.sectionInfo[id].section.setActive(false);
	this.activeSectionId = null;
	this.updateHash({section: null});
	this.close(this.sectionInfo[id].containerDivId, callback);
	}catch (e) { alert(e); }
}
nmtv.Site.prototype.showSection = function(sectionId, callback)
{
	if (this.isLoadingSection)
		return;
	if (this.isTransitioning)
		return;
	var sectionInfo = this.sectionInfo[sectionId];
	// not loaded yet, so setup the loading screen and wait for notification
	if (!sectionInfo.section) {
		if ($('#'+sectionInfo.frameId)[0].src != 'about:blank')
			return;
		this.isLoadingSection = true;
		this.showAnimAfterLoading = true;
		$('#'+sectionInfo.loadingDivId).css({display:'block'});
		$('#'+sectionInfo.loadingDivId+' > div.white, #'+sectionInfo.loadingDivId+' > div.black')
			.css({width:'0%'})
			.animate({width: '100%'}, {duration: 60*1000});
		$('#'+sectionInfo.frameId)[0].src = sectionInfo.frameSrc;
		var This = this;
		var listener;
		listener = function(event) {
			if (event.section != sectionInfo.section)
				return;
			setTimeout(function() {
				$('#'+sectionInfo.loadingDivId+' > div.white, #'+sectionInfo.loadingDivId+' > div.black')
					.stop();
				$('#'+sectionInfo.loadingDivId).css({display:'none'});
				This.isLoadingSection = false;
				This.removeEventListener(nmtv.events.Event.SECTION_LOAD, listener);
				This.showSection(sectionId, callback); // try again when loaded
				this.showAnimAfterLoading = false;
			}, 1000); // loading screen visible for at least one second
		};
		this.addEventListener(nmtv.events.Event.SECTION_LOAD, listener);
		if (this.activeSectionId) {
			if (this.sectionInfo[this.activeSectionId].section)
				this.sectionInfo[this.activeSectionId].section.setActive(false);
			this.close(this.sectionInfo[this.activeSectionId].containerDivId);
			this.activeSectionId = null;
		}
		return;
	}
	if (this.activeSectionId == sectionId)
		return;

	var oldActiveSectionId = this.activeSectionId;
	this.activeSectionId = sectionId;
		
	if (oldActiveSectionId)
		this.close(this.sectionInfo[oldActiveSectionId].containerDivId);
	for (var i in this.sectionInfo)
		if (i != sectionId)
			if (this.sectionInfo[i].section)
				this.sectionInfo[i].section.setActive(false);
	sectionInfo.section.setActive(true);
	var This = this;
	this.isTransitioning = true;

	this.open(sectionInfo.containerDivId, function(){
		This.isTransitioning = false;
		This.isFirstTransition = false;
		This.dispatchEvent(new nmtv.events.Event(nmtv.events.Event.SECTION_CHANGE));
		This.updateHash({section: sectionId});
		if (callback) callback();
	}, (oldActiveSectionId!=null || this.showAnimAfterLoading) && !this.isFirstTransition);
}
nmtv.Site.prototype.showBook = function(callback)
{
	this.showSection(nmtv.Section.BOOK, callback);
}
nmtv.Site.prototype.showBlog = function(callback)
{
	this.showSection(nmtv.Section.BLOG, callback);
}
nmtv.Site.prototype.showMap = function(callback)
{
	this.showSection(nmtv.Section.MAP, callback);
}
nmtv.Site.prototype.showBookPage = function(pageId)
{
	var This = this;
	this.showBook(function() {
		This.book.showBookPage(pageId);
	});
}
nmtv.Site.prototype.showBlogPost = function(postId)
{
	var This = this;
	this.showBlog(function() {
		This.blog.showBlogPost(postId);
	});
}
nmtv.Site.prototype.showBlogCategory = function(categoryId)
{
	var This = this;
	this.showBlog(function() {
		This.blog.showBlogCategory(categoryId);
	});
}
nmtv.Site.prototype.showMapMoment = function(momentId)
{
	var This = this;
	this.showMap(function() {
		This.map.showMapMoment(momentId);
	});
}


nmtv.Site.prototype.updateHashAll = function()
{
	var mainHash = this.calculateHash();
	for (var i in this.sections) {
		var section = this.sections[i];
//		var hash = section.calculateHash();
		section.updateHash(mainHash);
	}
}

nmtv.Site.prototype.calculateHash = function()
{
	return new nmtv.Hash(this.win);
}
nmtv.Site.prototype.updateHash = function(update)
{
	if (update instanceof nmtv.Hash == false)
		update = new nmtv.Hash(update);
	var hash = new nmtv.Hash(this.win);
	//alert(update);
	for (var i in update.props) {
		hash.set(i, update.props[i]);
	}
    
	if (this.win.location.hash == hash ||
		this.win.location.hash == '#'+hash)
		return;
	//alert(hash);
//	SWFAddress.setValue(hash.toString());
//	alert(this.window.location);
//	this.win.location.hash = hash.toString();
//	alert(hash.toString());
//	this.win.location.hash = '' + Math.floor(100*Math.random());
	//window.location.hash = '' + Math.floor(100*Math.random());
//	var hash = '#/blog_path,~blog~';
//	if (hash != this.win.location.hash)
	this.win.document.title = 'NomadNation ' + hash.toString();
//	this.win.location.hash = hash.toString();
    try {
        SWFAddress.setValueFromJS(hash.toString());
    } catch (ieException) {
    }
//	SWFAddress.setTitle('Nomad Nation ' + hash.toString());
//	alert(this.win.location);
//	this.win.location = 'www.google.com';
}
nmtv.Site.prototype.onSectionUrlChange = function(event)
{
	var hash = event.section.calculateHash();
	this.updateHash(hash);
}

nmtv.Section = function(name)
{
	nmtv.inherit(this, nmtv.events.EventDispatcher);
	
	this.name = name;
	this.site = null;
	this.nmtv = nmtv;
	this.isSearchable = false;
	this.queue = new Array();
}
nmtv.Section.BLOG = 'blog';
nmtv.Section.BOOK = 'book';
nmtv.Section.MAP = 'map';
nmtv.Section.prototype = new nmtv.events.EventDispatcher();
nmtv.Section.prototype._init = function(win)
{
	this.win = win;
	this._updateParent();
}
nmtv.Section.prototype._updateParent = function()
{
    document.domain = 'nomadnation.tv'; // ie
	var This = this;
//      try {
            if (This.win.parent && This.win.parent!=This.win && This.win.parent['nmtv'] && This.win.parent.nmtv['site']) {
                This.site = This.win.parent.nmtv.site;
                This.win.parent.nmtv.site.setSection(This.name, This);
            }
//    } catch (e) {
//        try {
//            if (this.nmtv.site) {
//                this.parent = this.nmtv.site;
//                this.nmtv.site.setSection(this.name, this);
//            }
//        } catch (e) {
//            alert(e);
//        }
//    }
}
nmtv.Section.prototype.enqueue = function(closure, context, args)
{
	var callback = nmtv.events.EventListener.wrap(closure, context, args);
	this.queue.push(callback);
}
nmtv.Section.prototype.runQueue = function()
{
	var callback;
	while (callback = this.queue.shift()) {
		try {
			callback.apply(null, []);
		} catch (e) {
			alert(e);
		}
	}
}
nmtv.Section.prototype.setActive = function(active) { /* abstract */ }
nmtv.Section.prototype.showBlogCategory = function(categoryId) { /* abstract */ }
nmtv.Section.prototype.showMapMoment = function(momentId) { /* abstract */ }
nmtv.Section.prototype.showBlogPost = function(postId) { /* abstract */ }
nmtv.Section.prototype.showBookPage = function(pageId) { /* abstract */ }
nmtv.Section.prototype.search = function(query) { /* abstract */ }
nmtv.Section.prototype.calculateHash = function() { /* abstract */ return {} }
nmtv.Section.prototype.updateHash = function(hash) { /* abstract */ }
nmtv.Section.prototype.showMap = function()
{
	if (this.site)
		this.site.showMap();
}
nmtv.Section.prototype.showBlog = function()
{
	if (this.site)
		this.site.showBlog();
}
nmtv.Section.prototype.showBook = function()
{
	if (this.site)
		this.site.showBook();
}

nmtv.Section.prototype.toString = function()
{
	return '[object nmtv.Section; name='+this.name+']';
}

nmtv.Section.prototype.showMapMoment = function(momentId)
{
	if (this.site)
		this.site.showMapMoment(momentId);
}
nmtv.Section.prototype.showBlogPost = function(postId)
{
	if (this.site)
		this.site.showBlogPost(postId);
}
nmtv.Section.prototype.showBlogCategory = function(categoryId) 
{
	if (this.site)
		this.site.showBlogCategory(categoryId);
}
nmtv.Section.prototype.showBookPage = function(pageId)
{
	if (this.site)
		this.site.showBookPage(pageId);
}


nmtv.SectionInfo = function(sectionId)
{
	this.sectionId = sectionId;
}
nmtv.SectionInfo.prototype.init = function(props)
{
	this.frameId = props.frameId;
	this.loadingDivId = props.loadingDivId;
	this.frameSrc = props.frameSrc;
	this.containerDivId = props.containerDivId;
}

} // namespace def

