/**
 * @required YAHOO.util.Dom
 * @required YAHOO.util.Event
 */

/**
 * Namespace
 */
target = window.target || {};
target.ui = target.ui || {};

/**
 * Enables New At Target page features.
 * @param {Object} cfg An object with any of the following optional string properties
 * &nbsp;&nbsp;featuresSWFPath:			features view swf file path
 * &nbsp;&nbsp;featuresSWFHeight: 		features view swf height
 * &nbsp;&nbsp;featuresXMLPath:			features view swf config xml path
 * &nbsp;&nbsp;featuresViewId:			features view element ID
 * &nbsp;&nbsp;allProductsViewId:		all products view element ID
 * &nbsp;&nbsp;resetAllProductsId:		reset all products view element ID
 * &nbsp;&nbsp;categoriesId:			category links parent element ID
 * &nbsp;&nbsp;categoriesItemTag:		category link item tag name
 * &nbsp;&nbsp;productsId:				products parent element ID
 * &nbsp;&nbsp;productsItemTag:			products item tag name
 * &nbsp;&nbsp;productsItemLinkClass:	products item link generic class name
 * &nbsp;&nbsp;productsItemClass:		products item generic class name
 * &nbsp;&nbsp;categoryClassPrefix:		category class prefix
 * &nbsp;&nbsp;asinIdPrefix:			ASIN id prefix
 * @class NewAtTarget
 * @constructor
 */
target.ui.NewAtTarget = (function(cfg) {	
	
	/**
     * The features view swf file path
     * @property featuresSWFPath
     * @type String
	 * @private
     */
	var featuresSWFPath = cfg.featuresSWFPath || "/images/nat/09/flash/NewAtTarget_V3.swf";
	
	/**
     * The features view swf height
     * @property featuresSWFHeight
     * @type Number
	 * @private
     */
	var featuresSWFHeight = cfg.featuresSWFHeight || 621;

	/**
     * The features view swf config xml path
     * @property featuresXMLPath
     * @type String
	 * @private
     */
	var featuresXMLPath = cfg.featuresXMLPath || "/images/newat_shell_config.xml";
	
	/**
     * Features SWFAddres Override Query Var
     * @property featureQueryVar
     * @type String
	 * @private
     */
	var featureQueryVar = cfg.featureQueryVar || "FlashExtra";
	
	/**
     * The features view element ID
     * @property featuresId
     * @type String
	 * @private
     */
	var featuresViewId = cfg.featuresViewId || "natFeaturesView";

	/**
     * The all products view element ID
     * @property allProductsId
     * @type String
	 * @private
     */
	var allProductsViewId = cfg.allProductsViewId || "natAllProductsView";
	
	/**
     * The reset all products view element ID
     * @property resetAllProductsId
     * @type String
	 * @private
     */
	var resetAllProductsId = cfg.resetAllProductsId || "natResetAllProducts";
	
	/**
     * The left menu links parent element ID
     * @property menuId
     * @type String
	 * @private
     */
	var menuId = cfg.menuId || "natMenu";
	
	/**
     * The category links parent element ID
     * @property categoriesId
     * @type String
	 * @private
     */
	var categoriesId = cfg.categoriesId || "natCategories";
	
	/**
     * The category link item tag name
     * @property categoriesItemTag
     * @type String
	 * @private
     */
	var categoriesItemTag = cfg.categoriesItemTag || "a";
	
	/**
     * The products parent element ID
     * @property productsId
     * @type String
	 * @private
     */
	var productsId = cfg.productsId || "natProducts";
	
	/**
     * The products item tag name
     * @property productsItemTag
     * @type String
	 * @private
     */
	var productsItemTag = cfg.productsItemTag || "li";
	
	/**
     * The products item link generic class name
     * @property productsItemLinkClass
     * @type String
	 * @private
     */	
	var productsItemLinkClass = cfg.productsItemLinkClass || "natProductLink";
	
	/**
     * The products item generic class name
     * @property productsItemClass
     * @type String
	 * @private
     */
	var productsItemClass = cfg.productsItemClass || "natProduct";
	
	/**
     * The category class prefix
     * @property categoryClassPrefix
     * @type String
	 * @private
     */
	var categoryClassPrefix = cfg.categoryClassPrefix || "natCat_";
	
	/**
     * The ASIN id prefix
     * @property asinIdPrefix
     * @type String
	 * @private
     */
	var asinIdPrefix = cfg.asinIdPrefix || "natASIN_";
	
	/**
     * The category table
     * @property categories
     * @type Object
	 * @private
     */
	var categories = null;
	
	/**
     * Boolean indicating if features view is available
     * @property featuresAvailable
     * @type boolean
	 * @private
     */
	var featuresViewAvailable = false;
	
	/**
	 * Provides Visual Sciences tracking of quick info triggers
	 * @property trackerQuickInfo
	 * @type object
	 * @private
	 */
	var trackerQuickInfo = null;
	
	/**
	 * Provides Visual Sciences tracking of product filtering
	 * @property trackerProductFilter
	 * @type object
	 * @private
	 */
	var trackerProductFilter = null;
	
	/**
     * A shortcut to YAHOO.util.Dom
     * @property Dom
     * @type object
	 * @private
     */
	var Dom = YAHOO.util.Dom;

	/**
     * A shortcut to YAHOO.util.Event
     * @property Event
     * @type object
	 * @private
     */
	var Event = YAHOO.util.Event;
	
	// before we init the features swf, check for a query string var and 
	// add it as a hash tag for swfaddress
	if (! window.location.hash && window.location.toString().indexOf(featureQueryVar) > -1) {
		var pattern = new RegExp(featureQueryVar + "=([^\&]+)");
		var hash = (window.location.toString().match(pattern) || [null, null])[1];
		
		if (hash) {
			setTimeout(function() {
				SWFAddress.setValue(hash);
			}, 0);
		}
	}
	
	/**
	 * Adds the Features flash experience to the page and
	 * determines whether or not to show the Features view
	 * based on whether or not the natFeatures DIV has been
	 * written to by swfobject
	 * @method setupFeatures
	 * @private
	 */
	var setupFeatures = function() {
		if (Dom.get(featuresViewId)) {
						
			var so = new SWFObject(featuresSWFPath, "shell", "730", featuresSWFHeight, "9.0.45", "#FFFFFF"); 
			so.addParam("wmode", "opaque");
			so.addVariable("config", featuresXMLPath);
			so.write(featuresViewId);  // Set this to the div id where the flash should be embedded
			
			featuresViewAvailable = Dom.get(featuresViewId).innerHTML.length ? true : false;
		}

		if (featuresViewAvailable) {
			Dom.setStyle(allProductsViewId, 'display', 'none');
			Dom.setStyle(featuresViewId, 'display', 'block');
		} else {
			Dom.setStyle(featuresViewId, 'display', 'none');
			Dom.setStyle(allProductsViewId, 'display', 'block');
		}
	};
	
	/**
	 * Attempt to parse category links and products to build
	 * a mapping associating categories with their ASINs
	 * @method setupCategoryTable
	 * @private
	 */
	var setupCategoryTable = function() {
		if (categories != null) {
			return;
		}
				
		categories = { titles: [], asins: [] };

		var matchedHTML = null;		
		var classNameRegx = new RegExp("\\sclass=(\"|')[^\\1]*?("+categoryClassPrefix+"[\\w]+)[^\\1]*?\\1", "");
		var className = '';

		var catHTML = Dom.get(categoriesId).innerHTML;
		var catRegx = new RegExp("<"+categoriesItemTag+"\\s+?[^>]*?>.+?<\/"+categoriesItemTag+">", "g");
		var catTitleRegx = new RegExp(">([^<]+)<\/"+categoriesItemTag+">", "");
		var catTitle = '';

		// var catRegxTestHTML = '<li><a href="#nat" class="natCategory_2">Women\'s dresses</a></li>';
		// alert(classRegx.exec(catRegxTestHTML).join('|'));
		// alert(catTitleRegx.exec(catRegxTestHTML).join('|'));

		var prodHTML = Dom.get(productsId).innerHTML;
		var prodRegx = new RegExp("<"+productsItemTag+"\\s+?[^>]*?>", "g");
		var prodIdRegx = new RegExp("\\sid=(\"|')("+asinIdPrefix+"\\w+)\\1", "");
		var prodId = '';
		
		// var prodRegxTestHTML = '<li class="natProduct natCategory_2" id="natASIN_B001K64Y7S">';
		// alert(classRegx.exec(prodRegxTestHTML).join('|'));
		// alert(prodIdRegx.exec(prodRegxTestHTML).join('|'));
		
		while (matchedHTML = catRegx.exec(catHTML)) {
			className = classNameRegx.exec(matchedHTML)[2];
			catTitle = catTitleRegx.exec(matchedHTML)[1];
			categories.titles[className] = catTitle;
			// alert("category: "+className+"=\""+categories.titles[className]+"\"");
		}
		
		while (matchedHTML = prodRegx.exec(prodHTML)) {
			className = classNameRegx.exec(matchedHTML)[2];
			prodId = prodIdRegx.exec(matchedHTML)[2];
			categories.asins[prodId] = className;
			// alert("asin: "+prodId+"=\""+className+"\"");
		}
	};
	
	/**
	 * Sets up category links to filter product listing
	 * @method setupCategoryLinks
	 * @private
	 */
	var setupCategoryLinks = function() {
		// if (categories == null) {
		// 	setupCategoryTable();
		// }
		
		var menuEl = Dom.get(menuId);
		var menuLinks = menuEl.getElementsByTagName('a');
		
		var categoriesEl = Dom.get(categoriesId);
		var categoryLinks = categoriesEl.getElementsByTagName('a');
		
		var l = null;
		
		for (l in menuLinks) {
			Event.addListener(menuLinks[l], 'click', categoryLinkClick, {}, this);
		}
		
		for (l in categoryLinks) {
			Event.addListener(categoryLinks[l], 'click', categoryLinkClick, {}, this);
		}
		
		Event.addListener('couponOffers', 'click', target.ui.Coupons.showSelector, {}, target.ui.Coupons);
		
		// Event.addListener(resetAllProductsId, 'click', categoryLinkClick, {}, this);
	};

	/**
	 * Handles clicks on category links
	 * @param {Object} event the event object
	 * @method categoryLinkClick
	 * @private
	 */	
	var categoryLinkClick = function(e) {
		Event.preventDefault(e);
		var t = e.target || e.srcElement;
		filterProductsByCategory.call(this, t.className);
		try {
			var category = t.innerHTML.replace(/<[^>]*?>/g, '').replace(/^[\s\f\n\r]*/, '').replace(/[\s\f\n\r]*$/, '');
			trackerProductFilter.track('Filter_' + category);
		} 
		catch (e) {
			trackerProductFilter.track('Filter_' + t.className);
		}
	};
	
	/**
	 * Sets up quick info links on the product listing
	 * @method setupQuickInfoLinks
	 * @private
	 */
	var setupQuickInfoLinks = function() {
		var productItemLinks = Dom.getElementsByClassName(productsItemLinkClass, 'a', productsId);
		for (var p in productItemLinks) {
			Event.addListener(productItemLinks[p], "click", productItemLinkClick, {}, this);
		}
	};

	/**
	 * Handles clicks on product items
	 * @param {Object} event the event object
	 * @method productItemLinkClick
	 * @private
	 */		
	var productItemLinkClick = function(e) {
		Event.preventDefault(e);
		var t = e.target || e.srcElement;
		var ASIN = domGetAncestorByTagName(t, productsItemTag).getAttribute('id');
		var A = t.tagName.toLowerCase() == 'a' ? t : domGetAncestorByTagName(t, 'a');
		
		// var productItems = Dom.getElementsByClassName(productsItemClass, productsItemTag, productsId);
		// var i = 0, matched = false;
		
		// for (; i < productItems.length && !matched; i++) {
		// 			if (productItems[i].id == ASIN) {
		// 				matched = true;
		// 			}
		// 		}
		
		patch_hideCouponSelection();
		// if (matched) {
			window.invokeQuickInfo(ASIN.substring(asinIdPrefix.length), 'sc_newat_viewall'/* 'br_qi_1_'+i */, A);
		// }
		
		trackerQuickInfo.track("QuickInfo_" + ASIN.substring(asinIdPrefix.length));
		
		// Bugfix: force close button display
		showQuickInfoCloseButton();
	};
	
	/**
	 * Manually displays the Quick Info close button
	 * @method showQuickInfoCloseButton
	 * @private
	 */
	var showQuickInfoCloseButton = function() {
		var dragFrameClose = Dom.get(window.dragFrameCloseId);
		// dragFrameClose.className = '';
		dragFrameClose.getElementsByTagName('a')[0].className = 'close';
	};
	
	/**
	 * Sets up view selector link interaction
	 * @method setupViewSelectors
	 * @private
	 */
	var setupViewSelectors = function() {
		var viewSelectors = document.createElement("label");
		viewSelectors.id = "natViewSelector";
		viewSelectors.innerHTML = '<strong>View:</strong> <a href="" id="featuresViewSelector" class="toggle">Features</a> or All Products';
		Dom.insertAfter(viewSelectors, document.getElementById("natHeader"));
		
		var home = document.createElement("span");
		home.className = "homeLink";
		document.getElementById("natHeader").appendChild(home);
		
		Event.addListener(home, 'click', viewSelectorClick, 'features', this);
		Event.addListener('featuresViewSelector', 'click', viewSelectorClick, 'features', this);
	};
	
	/**
	 * Handles clicks on view selector links
	 * @param {Object} event the event object
	 * @method viewSelectorClick
	 * @private
	 */
	var viewSelectorClick = function(e, viewName) {
		Event.preventDefault(e);
		target.ui.NewAtTarget.toggleView(viewName);
	};
	
	/**
	 * Finds a html elements ancestor
	 * @param {Object} node the starting node object
	 * @param {String} tagName the ancestor tag name
	 * @method domGetAncestorByTagName
	 * @private
	 */		
	var domGetAncestorByTagName = function(node, tagName) {
		var ancestor = node;
		while (ancestor = ancestor.parentNode) {
			if (ancestor.nodeType == 1 && ancestor.tagName.toLowerCase() == tagName.toLowerCase()) {
				return ancestor;
			}
		}
		return null;
	};
	
	/**
	 * Filters the products listing by category
	 * @param {String} categoryName optional categoryName to filter the products with
	 * @method categoryLinkClick
	 * @private
	 */		
	var filterProductsByCategory = function(categoryName) {
		var productItems = Dom.getElementsByClassName(productsItemClass, productsItemTag, productsId);
		for (var p in productItems) {
			productItems[p].style.display = (categoryName == '' || Dom.hasClass(productItems[p], categoryName) ? 'block' : 'none');
		}
	};
	
	/**
	 * Patches various behavior to tailor for New At Target
	 * @method setupPatches
	 * @private
	 */
	var setupPatches = function() {
		Event.addListener('printCoupons', 'click', patch_hideQuickInfo, {}, this);
		Event.addListener('couponOffers', 'click', patch_hideQuickInfo, {}, this);
		// @see productItemLinkClick
		// @see invokeQuickInfo
		// @see invokeCouponSelection
	};
	
	/**
	 * Hides Quick Info when Coupon Selection is clicked
	 * @method patch_hideQuickInfo
	 * @private
	 */
	var patch_hideQuickInfo = function(e) {
		if (e) {
			Event.preventDefault(e);
		}
		try {
			Dom.addClass('LayersFrame', 'hidden');
			Dom.addClass('dragFrame', 'hidden');
			Dom.addClass('dragFrameClose', 'hidden');
		}
		catch (x) {;}
	};
	
	/**
	 * Hides Coupons Selection
	 * @method patch_hideCouponSelection
	 * @private
	 */
	var patch_hideCouponSelection = function(e) {
		if (e) {
			Event.preventDefault(e);
		}
		try {
			Dom.removeClass('couponSelection', 'active');
		}
		catch (x) {;}
	};
	
	/**
	 * Sets up Visual Science tracking properties:
	 *   trackerQuickInfo, trackerProductFilter
	 * @method setupVisualScienceTracking
	 * @private
	 */
	var setupVisualScienceTracking = function() {
		function Reporter(reportName) { 
			this.reportName_ = reportName; 
		};
		Reporter.prototype.track = function(state) {}; 

		function VisualScienceReporter(trackingUrl, reportName) { 
			Reporter.apply(this, [reportName]); 
			this.trackingUrl_ = trackingUrl; 
		} 
		VisualScienceReporter.prototype = new Reporter(); 
		VisualScienceReporter.prototype.track = function(pageName) { 
			// alert(pageName); // DEBUG
			var script = document.createElement("script"); 
			script.src = this.trackingUrl_ + "?site=" + this.reportName_ + "&pagename=" + pageName + "&cachedefeat=" + Math.random(); 
			script.type = "text/javascript"; 
			document.getElementsByTagName("HEAD")[0].appendChild(script);
		};
	
		trackerQuickInfo = new VisualScienceReporter("http://vs.target.com/flashtag.txt", "QuickInfo");
		trackerProductFilter = new VisualScienceReporter("http://vs.target.com/flashtag.txt", "ProductFilter");
	};
	
	return {	
		/**
	     * The quick info VisualScienceReporter
	     * @method trackerQuickInfo
		 * @static
	     */		
		trackQuickInfo: function(asin) {
			trackerQuickInfo.track.call(trackerQuickInfo, 'QuickInfo_'+asin);
		},
		
		/**
	     * The product filter VisualScienceReporter
	     * @method trackerProductFilter
		 * @static
	     */
		trackProductFilter: function(category) {
			trackerProductFilter.track.call(trackerProductFilter, 'Filter_'+category);
		},
		
		/**
		 * Initializes the NewAtTarget page dynamics
		 * @method initialize
		 * @static
		 */
		initialize: function() {
			setupVisualScienceTracking.call(this);
			setupFeatures.call(this);
			setupCategoryLinks.call(this);
			setupQuickInfoLinks.call(this);
			setupViewSelectors.call(this);
			setupPatches.call(this);
		},
		
		/**
		 * Returns a reference to the category table
		 * @method getCategories
		 * @return {Object} the category table. Has the following structure
		 * &nbsp;&nbsp;categoryName: [ASIN, ASIN, ASIN, ...],
		 * &nbsp;&nbps;categoryName: [ASIN, ASIN, ASIN, ...] ...
		 * @static
		 */
		getCategories: function() {
			return categories;
		},
		
		/**
		 * Toggles between Features and All Products views
		 * @param {String} viewName optional the view to show
		 * @method toggleView
		 */
		toggleView: function(viewName) {
			var display = '';
			
			if (!featuresViewAvailable) {
				return;
			}
			
			patch_hideQuickInfo();
			patch_hideCouponSelection();
			
			if (viewName == null) {
				Dom.setStyle(allProductsViewId, 'display', Dom.getStyle(allProductsViewId, 'display') == 'block' ? 'none' : 'block');
				Dom.setStyle(featuresViewId, 'display', Dom.getStyle(featuresViewId, 'display') == 'block' ? 'none' : 'block');
			} else {
				if (viewName == 'allProducts') {
					Dom.setStyle(featuresViewId, 'display', 'none');
					Dom.setStyle(allProductsViewId, 'display', 'block');
				} else {
					Dom.setStyle(allProductsViewId, 'display', 'none');
					Dom.setStyle(featuresViewId, 'display', 'block');
				}
			}
		},
		
		/**
		 * Invokes the Quick View 
		 * @method invokeQuickView
		 */
		invokeQuickInfo: function(ASIN) {
			patch_hideCouponSelection();
			window.invokeQuickInfo(ASIN, 'sc_newat_viewfeatures', null);
			trackerQuickInfo.track("QuickInfo_" + ASIN);
			// Bugfix: force close button display
			showQuickInfoCloseButton();
		},
		
		/**
		 * Invokes the Coupon Selection
		 * @method invokeCouponSelection
		 */
		invokeCouponSelection: function() {
			patch_hideQuickInfo();
			target.ui.Coupons.showSelector.call(target.ui.Coupons, { 'preventDefault': new Function('') });
		}
	};
	
})({});

YAHOO.util.Event.onDOMReady(target.ui.NewAtTarget.initialize, {}, target.ui.NewAtTarget);
