var PartExplorer = function(){
    var provider,
		layout,
		tree,
		treeViewLock = false,
		partWidget,
		partNoSearch,
		brandBrowseWidget,
		brandCategoryBrowseWidget,
		clearSearchDelayedTask,
		resetBrandCategoryBrowseWidgetDelayedTask,
		categoryBrowseWidget,
		menu,
		orderDataModel,
		shuttingDown;

    return {
		version: clientVersion,
		agent: clientAgent,
		build: clientBuild,

        init: function(){
            // initialize state manager, we will use cookies
			provider = new PollingCookieProvider();
			//provider = new PollingServletProvider({ url: 'session', interval: 1000 });
			YAHOO.ext.state.Manager.setProvider(provider);

			// Set the version number in the heading
			var version_element = getEl('version');

			if (version_element)
			{
				version_element.update('v' + this.version + '-' + this.agent);
			}

			// set the build number in the footer
			var build_element = getEl('buildNumber');

			if (build_element)
			{
				build_element.update(this.build);
			}

            // create the main layout
            layout = new YAHOO.ext.BorderLayout(document.body, {
                north: {
                    titlebar: false
                },

                west: {
					collapsible: true,
					hideOnLayout: true,
					split:true,
					initialSize: 300,
					minSize: 175,
					titlebar: false,
					tabPosition: 'top',
					cmargins: {top:2,bottom:2,right:2,left:2},
					resizeTabs: true
                },

                center: {
					titlebar: false,
					autoScroll: true,
					tabPosition: 'top',
					closeOnTab: true
                },

				south: {
					titlebar: false,
					autoScroll: true,
					collapsible: false,
					split: false
				}
            });

			// tell the layout not to perform layouts until we're done adding everything
			layout.beginUpdate();

			menu = new BorderLayoutMenuBar("main-menu", { autosubmenudisplay:true, showdelay:250, hidedelay:750, lazyLoad: true});
			menu.render();

			//initialize our tree
			tree = new YAHOO.ext.tree.TreePanel('tree', {
				rootVisible: false
			});

			var treeLoader = new  CITTreeLoader({dataUrl: PartExplorer.makeJSDataURLPrefix(0) + '.js'});
			treeLoader.on("loadexception", PartExplorer.serverFailure);

			var root = new YAHOO.ext.tree.AsyncTreeNode({
				text: 'root',
				allowDrag:false,
				allowDrop:false,
				loader: treeLoader,
				applyLoader: true
			});

			root.on('load', PartExplorer.rootNodeLoaded);

			tree.setRootNode(root);
			tree.on("click", PartExplorer.handleClick);
			tree.render();

			//this.loadOrderForm();

			//part list and detail setup
			partWidget = new PartWidget('PartWidget', 'part-filter-input', 'part-list', 'part-detail', 'part-detail-view', [], 20);

			//search / browse setup
			partNoSearch = getEl('partNoSearch');

			brandBrowseWidget = new QuickBrowseWidget('brandBrowse', '0', '-brand', 'form1');
			brandCategoryBrowseWidget = new QuickBrowseWidget('brandBrowse', '0', '-brand.category', 'form2', true);

			brandCategoryBrowseWidget.disable();

			brandBrowseWidget.on('selectionchange', PartExplorer.browseSelection, PartExplorer);
			brandBrowseWidget.on('deadend', PartExplorer.browseDeadEnd, PartExplorer);

			//uncomment if you want a change in part category selection to clear results first
			//brandCategoryBrowseWidget.on('selectionchange', PartExplorer.browseSelection, PartExplorer);

			//comment out if you don't want brand categories auto searching
			brandCategoryBrowseWidget.on('deadend', PartExplorer.browseDeadEnd, PartExplorer);

			resetBrandCategoryBrowseWidgetDelayedTask = new YAHOO.ext.util.DelayedTask();
			clearSearchDelayedTask = new YAHOO.ext.util.DelayedTask();

			categoryBrowseWidget = new QuickBrowseWidget('categoryBrowse', '0', '-category');
			categoryBrowseWidget.on('selectionchange', PartExplorer.browseSelection, PartExplorer);
			categoryBrowseWidget.on('deadend', PartExplorer.browseDeadEnd, PartExplorer);


			//setup layout regions
			layout.add('north', new YAHOO.ext.ContentPanel('north'));

			layout.add('west', new YAHOO.ext.ContentPanel('categories', {title: 'All Brands', fitToFrame: true}));
			layout.add('west', new YAHOO.ext.ContentPanel('search', { title: 'Search / Quick Browse', fitToFrame: true}));

			layout.add('center', new YAHOO.ext.NestedLayoutPanel(partWidget.layout, { title: 'Search Results', fitToFrame: true}));

			layout.add('south', new YAHOO.ext.ContentPanel('south'));

			//layout.showPanel('categories');

			layout.restoreState();

			//remove loading indicator
			getEl('loading').remove();
			layout.endUpdate();

			layout.getRegion('west').tabs.getTab('search').on('activate', PartExplorer.highlightSearchForm, PartExplorer);
        },

		makeJSDataURLPrefix: function(parts_app_node_id) {
			return "js_data/" + parts_app_node_id.toString();
		},

    	handleClick: function(node) {
    		if (node.isLeaf())
    		{
    			partWidget.loadDoc(PartExplorer.makeJSDataURLPrefix(node.attributes.parts_app_node_id) + "-parts.js", null);

    			//make sure the partWidget is showing
    			layout.showPanel('PartWidget');

				partWidget.collapsePartDetail();
    		}
    		else
    		{
    			partWidget.clear();
    			node.toggle();
    			return false;
    		}
    	},

        showBranch: function(parts_app_node_id, title) {

			if (!treeViewLock)
			{
				treeViewLock = true;

				var panel = layout.findPanel('categories');
				title = title ? title : 'Category';

				panel.setTitle(title);

				var root = tree.getRootNode();
				root.rendered = false;

				var children = root.childNodes;

				for (var i = children.length - 1; i >= 0; i--)
				{
					root.removeChild(children[i]);
				}

				root.attributes.loader = null;
				root.loaded = false;

				root.attributes.loader = new CITTreeLoader({dataUrl: PartExplorer.makeJSDataURLPrefix(parts_app_node_id) + '.js'});
				root.expand();

				//clear our part widget
				partWidget.clear();

				//reset category quick browse
				categoryBrowseWidget.reset();

				//make sure brand browser interface defaults to this selected brand
				brandBrowseWidget.loadIdAtLevel(parts_app_node_id, 0);

				//make sure this tab is showing - removed as per Trac #21
				//layout.showPanel('categories');
			}
        },

		rootNodeLoaded: function() {
			treeViewLock = false;
		},

		browseSelection: function(quickBrowseWidget, form, level, selectedId) {
			if (quickBrowseWidget == brandBrowseWidget)
			{
				if (level == 0 && selectedId == false)
				{
					brandCategoryBrowseWidget.disable();
				}
				else
				{
					brandCategoryBrowseWidget.disable();
					resetBrandCategoryBrowseWidgetDelayedTask.delay(250, brandCategoryBrowseWidget.reset, brandCategoryBrowseWidget, [selectedId]);
				}
			}

			//clear the part widget, but try to only do it once
			if (level > 0 || selectedId)
			{
				clearSearchDelayedTask.delay(500, PartExplorer.clearSearch, PartExplorer);
			}
		},

		browseDeadEnd: function(quickBrowseWidget) {
			//cancel the clear and do a search instead
			clearSearchDelayedTask.delay(500, PartExplorer.search, PartExplorer, [quickBrowseWidget.form.dom]);
		},

		clearSearch: function() {
			partWidget.clear();
		},

		search: function(form) {
			switch (form.getAttribute("id"))
			{
				case 'partNoSearch':
					brandBrowseWidget.reset();
					categoryBrowseWidget.reset();
					brandCategoryBrowseWidget.reset();
					break;

				case 'brandBrowse':
					partNoSearch.dom.reset();
					categoryBrowseWidget.reset();
					break;

				case 'categoryBrowse':
					partNoSearch.dom.reset();
					brandBrowseWidget.reset();
					brandCategoryBrowseWidget.reset();
					break;
			}

			if (form.part_no && typeof form.part_no.value != 'undefined' && !form.part_no.value.length)
			{
				alert('Please Enter at Least One Character');
				return false;
			}

			partWidget.loadDoc("search", PartExplorer.searchCallback, YAHOO.util.Connect.setForm(form));

			//make sure parts tab is showing
			layout.showPanel('PartWidget');

			//collapse the part detail
			partWidget.collapsePartDetail();

			return false;
		},

		searchCallback: function(response) {
			if (response.status != 200)
			{
				alert("An error occurred while searching, is the application still running?");
			}
			else if (response.responseText.length <= 2)
			{
				alert("No search results found");
			}
		},

		loadPartDetail: function(parts_app_node_id, sku) {
			partWidget.loadPartDetail(parts_app_node_id, sku);

			layout.showPanel('PartWidget');

			return false;
		},

		loadOrderForm: function() {
			if (!shuttingDown)
			{
				frames['orderForm'].location.href = 'order_form.html';
				this.showOrderForm();
			}
		},

        showOrderForm: function() {
        	provider.poll();
        	layout.showPanel('orderForm');
        },

		highlightOrderForm: function() {
			layout.getRegion("center").tabs.getTab('orderForm').setText('<div style="font-weight: bold; color: red">Order Form</div>');
			layout.getRegion("center").tabs.getTab('orderForm').setTooltip('Items have been added to your order form');
		},

		unhighlightOrderForm: function() {
			layout.getRegion("center").tabs.getTab('orderForm').setText('Order Form');
		},

		highlightSearchForm: function() {
			var field = getEl('part_no');

			if (field)
			{
				field.dom.select();
				field.dom.focus();
			}
		},

		setOrderTotal: function(dataModel) {
			var total = 0;

			for (var row = dataModel.getRowCount() - 1; row >= 0; row--)
			{
				total += dataModel.getValueAt(row, 5)
			}

			var total_discount = 0;
			var discount = 0;

			var formValues = dataModel.state.get('formValues');

			if (formValues && formValues.selDiscount)
			{
				discount = formValues.selDiscount / 1;
			}

			total -= total * discount / 100;

			total = (Math.round(total*100))/100;
			total = (total == Math.floor(total)) ? total + '.00' : ( (total*10 == Math.floor(total*10)) ? total + '0' : total);

			if (discount)
			{
				total += ' (w/ ' + discount + '% discount)';
			}

			getEl('orderTotal').dom.innerHTML = total;
		},

        addPart: function(parts_app_node_id, quantity, comment) {

			quantity = +quantity;

			if (quantity != NaN && quantity >= 0)
			{
				var cb = {
					success: PartExplorer._addPart,
					failure: PartExplorer._addPartFailure,
					scope: this,
					argument: { quantity: quantity, comment: comment }
				};

				YAHOO.util.Connect.asyncRequest('GET', PartExplorer.makeJSDataURLPrefix(parts_app_node_id) + '.js', cb);
			}
			else
			{
				alert('Not a Valid Quantity');
			}
        },

        _addPart: function(response) {
	        var json = response.responseText;
	        try {
	            var o = eval('('+json+')');

	            var quantity = response.argument.quantity;

	            if (!quantity)
	            {
	            	quantity = o[0].standard_qty;
	            }

				var comment = response.argument.comment;

				if (!comment)
				{
					comment = '';
				}

				//check that quantity is a multiple of standard quantity
				if (quantity % o[0].standard_qty == 0)
				{
					orderDataModel.addRow([null, o[0].sku, quantity, o[0].product_name, o[0].dnet_price, o[0].dnet_price * quantity, comment, o[0].standard_qty]);
					PartExplorer.highlightOrderForm();
				}
				else
				{
					alert('Quantity must be a multiple of ' + o[0].standard_qty);
				}
	        }catch(e){
	            PartExplorer._addPartFailure(response);
	        }
        },

        _addPartFailure: function(response) {

        },

		quickAddPart: function(form) {
			if (form)
			{
				if (form.query.value.length > 0)
				{
					var cb = {
						success: PartExplorer._quickAddPart,
						failure: PartExplorer._addPartFailure,
						scope: this,
						argument: { form: form }
					};

					YAHOO.util.Connect.setForm(form);
					YAHOO.util.Connect.asyncRequest('GET', 'search', cb);
					return false;
				}
			}

			alert('Please enter a valid part #');
			return false;
		},

		_quickAddPart: function(response) {
	        var json = response.responseText;
	        try {
	            var o = eval('('+json+')');

				if (o.length > 1 && response.argument.form)
				{
					alert('Search returned more than one possibility, please select one and add it');

					PartExplorer.search(response.argument.form);
				}
				else if (o.length == 1)
				{
					var quantity = o[0][5];
					var comment = '';

					if (response.argument.form && response.argument.form.qty)
					{
						if (response.argument.form.qty.value != '')
						{
							quantity = response.argument.form.qty.value;
						}
					}

					if (response.argument.form && response.argument.form.comment)
					{
						if (response.argument.form.comment.value != '')
						{
							comment = response.argument.form.comment.value;
						}
					}

					if (!response.argument.form || !response.argument.form.qty || (o[0][5] > 0 && quantity % o[0][5] > 0 || quantity <= 0))
					{
						alert('Your quantity must be a multiple of ' + o[0][5]);

						if (response.argument.form.qty)
						{
							response.argument.form.qty.focus();
						}

						return;
					}

					if (quantity != null && quantity != '')
					{
						PartExplorer.addPart(o[0][0], quantity, comment);
					}
					else
					{
						if (response.argument.form.part_no)
						{
							response.argument.form.part_no.focus();
						}
						return;
					}
				}
				else
				{
					alert('Could not find your part');

					if (response.argument.form.part_no)
					{
						response.argument.form.part_no.focus();
					}
					return;
				}

				if (response.argument.form.part_no)
				{
					response.argument.form.part_no.value = '';

					if (response.argument.form.qty)
					{
						response.argument.form.qty.value = '';
					}

					if (response.argument.form.comment)
					{
						response.argument.form.comment.value = '';
					}

					response.argument.form.part_no.focus();
				}
	        }catch(e){
				alert(e.toString());
				PartExplorer._addPartFailure(response);
	        }
		},

		showDNET: function(form) {
				getEl(form).toggleClass('show_dnet');
		},

		maximizeWindow: function() {
			var offset = (	navigator.userAgent.indexOf("Mac") != -1 ||
									navigator.userAgent.indexOf("Gecko") != -1 ||
									navigator.appName.indexOf("Netscape") != -1) ? 0 : 4;
			window.moveTo(-offset, -offset);
			window.resizeTo(screen.availWidth + (2 * offset),
											screen.availHeight + (2 * offset));
		},

		shutdown: function(onclick) {
			shuttingDown = true;
		},

		serverFailure: function(state) {
			if (state.setReportFailure)
			{
				state.setReportFailure(false);
			}

			if (!window.confirm('ERROR! The CD Catalog Application seems to have quit, please make sure its running and click OK to continue'))
			{
				document.open('text/html');
				document.write(
					'<html>' +
						'<head><title>CD Catalog is no longer running</title></head>' +
						'<body>' +
							'<h3>CD Catalog Application does not seem to be running or has encountered an unrecoverable error!</h3>' +
							'<p>Please close this window and restart the CD Catalog Application to continue</p>' +
							'<hr/>' +
							'<h3>Did you exit the application (through the system tray) before closing the browser window?</h3>' +
							'<p>Though the application automatically launches the browser for you, it is not possible (and usually not desired) for it' +
							' to also automatically close your browser window.  If you intentionally shutdown the application then you can simply close' +
							' this window, this message is only to notify the user that the page is no longer able to get the data it requires.</p>' +
						'</body>' +
					'</html>'
				);

				document.close();
			}
			else
			{
				if (state.setReportFailure)
				{
					state.setReportFailure(true);
				}
			}
		}
    };
}();

YAHOO.ext.EventManager.onDocumentReady(PartExplorer.init, PartExplorer, true);