var Dom = YAHOO.util.Dom;
var Event = YAHOO.util.Event;

function Store() {
	//this.broswer = new BrowserDetectLite();
	this.ObjectAccessor = new ObjectAccessor();
	this.debug = new Debug(false); 		// to turn off = new Debug(false);
	this.item_data = new Array();
	this.sort_data = {
      1: {price: [], date: [], all: []},
      4: {price: [], date: [], all: []},
      5: {price: [], date: [], all: []},
	  6: {price: [], date: [], all: []},
      7: {price: [], date: [], all: []},
	  8: {price: [], date: [], all: []},
      9: {price: [], date: [], all: []},
	  10: {price: [], date: [], all: []},
      11: {price: [], date: [], all: []},
	  12: {price: [], date: [], all: []},
	  13: {price: [], date: [], all: []},
	  14: {price: [], date: [], all: []}
  };
	this.shelf_data = new Array();
	this.store_data = new Array();
  this.store_map = [];
	this.npc_data = new Object();
	this.navigate_start = 0;
	this.navigate_end = 3;
	this.all_divs = new Array('npc-dialog','npc-dialog-contents');
	this.npc_1_count = 1;
	this.npc_2_count = 1;
	this.npc_buttons = new Array();
	
	this.dialog = new Object();
	//this.debug.write('store js object loaded.');
    
    // Quest-related
    this.has_seen_quests = false;   // Have they seen the quest dialog yet?
    this.nav_page = 1;
    this.current_quest_dialog = 0;

    this.currentTab = '';
    this.tab_page_num = {};
    this.tab_sort = {};

    this.currentSortType = 'price';

    this.color_sort = 'all';
    this.change_from_init = false;
    // flag whether or not to disable the npc chat bubble
    this.hide_timer_id = 0;
};



//---------------------------------------------------------------------------//
// register and show mouseovers
//---------------------------------------------------------------------------//

Store.prototype.register_mouseover=function(_text,_image,_action,_class,_lid) 
{

	// create a temp object to hold the mouseover data.
	var temp_button_data = new Object();
	temp_button_data.text = _text;
	temp_button_data.image = _image;
	temp_button_data.action = _action;
	temp_button_data.classname = _class;
	temp_button_data.lid = _lid; //javascript launch id for flash env
	// push it onto the buttons array.
	this.npc_buttons.push(temp_button_data);
	//this.debug.write('registered mouseover:'+_text);
	
	return true;
};

Store.prototype.make_mouseover_div=function(_mouseoverkey, _has_quest){
	
	// force shit to be integers
	var _m = parseInt(_mouseoverkey);
	
	//this.debug.write(' getting div: mouseover_'+_m);

	var div=this.ObjectAccessor.find("mouseover_"+_m);
	if (isObject(div))
	{
		// get the mouseover data.
		var mdata = this.npc_buttons[_m];
		var button_html = '';
        var quest_chat_overlay = '';
		
		////this.debug.write(' action:'+_m);
		
		if (mdata.action) 
		{
			//this.debug.write('action:'+mdata.action);
            if (_has_quest) {
                button_html+='<a href="'+'javascript:store.npc_quest(\'ordered\')'+'">';
                quest_chat_overlay = '<span class="quest_chat_overlay" title="Quest in Progress">&nbsp;</span>'
            }
            else {
                button_html+='<a href="'+mdata.action+'">';
            }
		}
		
		button_html+='<div id="mouseover_img_'+_m+'"' +
			' alt="'+mdata.text+'" title="'+mdata.text+'" class="npc_buttons ' +mdata.classname+'">'+quest_chat_overlay+'</div>';
		
		if (mdata.action) 
		{
			button_html+='</a>';
		}
		
		// populate the div with the appropriate data.
		div.title = mdata.text;
		div.innerHTML = button_html;
		var imgtag = store.ObjectAccessor.find("mouseover_img_"+_m);
		div.style.cursor="hand";

    Dom.addClass(div, 'npc_buttons');
		//this.debug.write('mouseover assigned: '+_m);
	} else {
		//this.debug.write('mouseover object failed: '+_m);
	}
	return div;
};

Store.prototype.make_mouseovers=function()
{
	// loop through all defined mouseovers and show them.
	var _m=0;
	for (_m=0; _m<this.npc_buttons.length; _m++)
	{
    if (this.npc_buttons[_m].image == 'story_link') {
        this.addLink(this.npc_buttons[_m].action, this.npc_buttons[_m].text,this.npc_buttons[_m].lid);
    } else {
        // need to pass in whether there is an active quest
        var _has_quest = this.npc_buttons[_m].image == 'quest_chat_bubble';
	  	this.make_mouseover_div(_m, _has_quest);
    }
	}
}

//---------------------------------------------------------------------------//
// show and move the navigation divs.
//---------------------------------------------------------------------------//

Store.prototype.move_navigate=function(_direction)
{
  var new_page_num = 0;

  if (_direction == 'up') {
    if ( (this.nav_page + 1) > 3) {
        return;
    }

    new_page_num = this.nav_page + 1;
  } else if (_direction == 'down') {
    if ( (this.nav_page - 1) < 1) {
        return;
    }

    new_page_num = this.nav_page - 1;
  } else {
     /* set the current store as 'active' */
    var i = store.store_map[storeid];
    store.shiftSprite(store.store_data[i]['button'], 'add');

    new_page_num = parseInt(this.store_map[storeid] / 8) + 1;
     /* hide the first page */
    if (new_page_num != 1) {
      this.nav_page = 1;
    }
  }

  Dom.setStyle('nav_page' + this.nav_page, 'display', 'none');
  Dom.setStyle('nav_page' + new_page_num, 'display', 'block');

  this.nav_page = new_page_num;

  if (this.nav_page == 1) {
    Dom.removeClass('nav_right', 'nav-disabled');
    Dom.addClass('nav_left', 'nav-disabled');
  } else if (this.nav_page == this.navigate_end) {
    Dom.removeClass('nav_left', 'nav-disabled');
    Dom.addClass('nav_right', 'nav-disabled');
  } else {
    Dom.removeClass('nav_left', 'nav-disabled');
    Dom.removeClass('nav_right', 'nav-disabled');
  }
}

//---------------------------------------------------------------------------//
// store registration
//---------------------------------------------------------------------------//

Store.prototype.register_store=function(_storeid,_key,_name,_button) {
  this.store_map[parseInt(_storeid)] = this.store_data.length;
  this.store_data.push({id: parseInt(_storeid),
                        key: _key,
                        name: _name,
                        button: _button});

	return true;
};


//---------------------------------------------------------------------------//
// NPC and npc dialog registration and display.
//---------------------------------------------------------------------------//

Store.prototype.register_npc=function(_npcid,_npcname,_img) {
    if (typeof(this.npc_count) == 'undefined') {
        this.npc_count = 0;
    }
	if (!isObject(this.npc_data[_npcid])) {
		this.npc_data[_npcid] = new Array();
        // keep track of how many npcs there are in this store
        ++this.npc_count;
	}
	
	this.npc_data[_npcid].name = _npcname;
	this.npc_data[_npcid].img = _img;
	////this.debug.write('registered diag:'+_text);
	
	return true;
};

Store.prototype.register_dialog=function(_npcid,_type,_text) {
	
	if (!isObject(this.dialog[_npcid])) {
		this.dialog[_npcid] = new Object();
	}
	
	if (!isArray(this.dialog[_npcid][_type])) {
		this.dialog[_npcid][_type] = new Array();
	}
	
	this.dialog[_npcid][_type].push(_text);
	////this.debug.write('registered diag:'+_text);
	
	return true;
};

Store.prototype.npc_chat=function(_npcid)
{
	if (_npcid != this.current_npc)
        this.has_seen_quests = false;   // If we haven't shown quest dialog yet for the NPC we're switching to, show that first!
    
	var chat_diag = this.dialog[_npcid].chat;
	var npc_name = this.npc_data[_npcid].name;
	
	var randkey = Math.floor(Math.random()*chat_diag.length)
	
	////this.debug.write('diag:'+this.debug.var_dump(chat_diag));
	
	var box_html = '';
	box_html += '<div id="npc-dialog-name">'+npc_name+':</div>';
	box_html += '<div id="npc-dialog-text">';
	box_html += chat_diag[randkey];
	box_html += '</div>';
	
	// make sure that the proper npc is showing.
	this.show_npc(_npcid);
    
    // make sure that the proper npc name is showing
    // if the store has more than one npc we're going to have to swap the npc name graphic
    if (this.npc_count > 1) {
        var npc_name_parts = npc_name.toLowerCase().split(' ');
        var npc_name_img = document.getElementById('npc_name');
        npc_name_img.src = 'http://'+GAIA_config('graphics_server')+'/images/store2/hd_' + npc_name_parts[0] + '_210x25.gif';
    }
	
	// then we hide everything else.
	this.hide_all();
	
	// and populate the npc's messsage with what we want him to say.
	var _div=this.ObjectAccessor.find("npc-dialog-contents");
	_div.innerHTML = box_html;
	
	var _parent=this.ObjectAccessor.find("npc-dialog");
		
	// then show it.
	//_div.style.visibility="visible";
	//_div.style.display="block";
	//_parent.style.visibility="visible";
	  //_parent.style.display="block";
	this.show_div("npc-dialog");
	this.show_div("npc-dialog-contents");
		
}

Store.prototype.npc_welcome=function()
{
	this.has_seen_quests = true;   // If quest dialog is available, it is the first thing shown
    
    var isQuest = false;
	var welcome_diag = this.dialog[this.current_npc].welcome;
    if(typeof(this.dialog[this.current_npc].quest) != "undefined"){
        welcome_diag = this.dialog[this.current_npc].quest;
        isQuest = true;
    }
	
	var randkey = Math.floor(Math.random()*welcome_diag.length);
	
	////this.debug.write('diag:'+this.debug.var_dump(chat_diag));
	
	var box_html = '';
    if(isQuest) {
/*        box_html += '<div id="npc-dialog-close" onClick="store.hide_all()"></div>'; */
        randkey=0;
        this.skip_dialog_click = true;
    }
	box_html += '<div id="npc-dialog-name">'+this.npc_data[this.current_npc].name+':</div>';
	box_html += '<div id="npc-dialog-text">';
	box_html += welcome_diag[randkey].replace('{name}',username);
	box_html += '</div>';
    

	// then we hide everything else.
	//this.hide_all();
	
	// and populate the npc's messsage with what we want him to say.
	var _div=this.ObjectAccessor.find("npc-dialog-contents");
	_div.innerHTML = box_html;
	
	// then show it.
	this.show_div("npc-dialog");
	this.show_div("npc-dialog-contents");

    if(!isQuest) {
        store.hide_timer_id = setTimeout(function(){
          store.hide_all();
        }, 10000);
    }
}

Store.prototype.quest_check=function()
{
    
    if (this.has_dialog('quest'))
    {
        //this.register_mouseover('Quest Update', 'story_link', 'javascript:store.npc_quest(\'ordered\')');
    }
    
}

Store.prototype.npc_quest=function(qd_loc)
{
    var npc_id;
    this.has_seen_quests = true;
    this.skip_dialog_click = true;

    
    // If the current NPC doesn't have quest dialog, but they reached this method, see if we can find an NPC that does...
    if (typeof(this.dialog[this.current_npc]['quest']) != "undefined")
    {
        npc_id = this.current_npc;
    }
    else
    {
        for(_npc_id in this.npc_data)
            if (typeof(this.dialog[_npc_id]['quest']) != 'undefined')
            {
                npc_id = _npc_id;
                break;
            }
    }
    
	var quest_diag = this.dialog[npc_id].quest;
    
    var randkey = 0;

    if(typeof(qd_loc) == "undefined") {
        randkey = Math.floor(Math.random()*quest_diag.length);
    }
    else{

        if(qd_loc == "ordered") {
            randkey =  this.current_quest_dialog + 1;
            if(randkey >= quest_diag.length) randkey= 0;
        }
        else{
            randkey = qd_loc;
        }
    }
    
    this.current_quest_dialog = randkey;

	var box_html = '<div id="npc-dialog-name">'+this.npc_data[this.current_npc].name+': </div>';
	box_html += '<div id="npc-dialog-text">';
	box_html += quest_diag[randkey].replace('{name}',username);
	box_html += '</div>';
	
	// then we hide everything else.
	this.hide_all();
	
	// and populate the npc's messsage with what we want him to say.
	var _div=this.ObjectAccessor.find("npc-dialog-contents");
	_div.innerHTML = box_html;
	
	// then show it.
    this.show_npc(npc_id);
	this.show_div("npc-dialog");
	this.show_div("npc-dialog-contents");
}

// _npc_id is optional. It can be excluded to look for results from any NPC in the store
Store.prototype.has_dialog=function(_type, _npc_id)
{
    // If there is no _npc_id specified, loop through all the NPCs to see if there is any quest dialog at all registered.
    if (typeof(_npc_id) == 'undefined')
    {
        for(_npc_id in this.npc_data)
            if (typeof(this.dialog[_npc_id][_type]) != 'undefined')
                return true;
    }
    else if (typeof(this.dialog[_npc_id][_type]) != 'undefined')
        return true;
    
    return false;
}

Store.prototype.show_npc=function(_npcid)
{
	if (this.current_npc != _npcid)
	{
		this.current_npc = _npcid;
		
		  var box_html = '<img src="'+buttonpath+this.npc_data[_npcid].img+'?' + GAIA_config('cache_value') + '" width=210 height=300 border=0 />';
		
		// and populate the npc's messsage with what we want him to say.
		var _div=this.ObjectAccessor.find("store-npc");
		_div.innerHTML = box_html;
		
    if (YAHOO.env.ua.ie == 6) {
      supersleight.fixIt('store-npc');
    }
		// then show it.
		//_div.style.visibility="visible";
		//this.show_div("npc-dialog");
	}
}




//---------------------------------------------------------------------------//
// Item registration, sort, and preview.
//---------------------------------------------------------------------------//

Store.prototype.register_item=function(_itemid,_group,_name,_desc,_type,_price,_gpass,_thumb,_jswin,_gender,_serial,_wishlistnonce, _created ) {
	
	// force shit to be integers
	var _i = parseInt(_itemid);
	var _g = parseInt(_group);
	var _s = parseInt(_serial); //parseInt(_serial);

  if (_g == 2) {
    _g = 1;
  }
	
	var _k = _i;
	
	/*
	if (typeof(_properties) != 'undefined' && _properties!='') 
	{
		var _prop = YAHOO.lang.JSON.parse(_properties);
	} 
	else {
		var _prop = new Object();	
	}
	*/
	
	// if the itemdata is not already defined, define it.
	if ( !isArray(this.item_data[_k]) ) {
		this.item_data[_k] = new Array();
		this.item_data[_k].group = _g;
		this.item_data[_k].name = _name;
		this.item_data[_k].desc = _desc;
		this.item_data[_k].type = _type;
		this.item_data[_k].price = _price;
		this.item_data[_k].gpass = _gpass;
		this.item_data[_k].thumb = _thumb;
		this.item_data[_k].gender = _gender;
		//this.item_data[_k].nosell = _sellback;
		this.item_data[_k].properties = new Object;
		this.item_data[_k].wishlistnonce = _wishlistnonce;
		this.item_data[_k].created = _created;
	}
	
	// set the sort order for price
		this.item_data[_k].jsbuy = _jswin;
		if (!isArray(this.sort_data[_g]['price'])) 
		{
			this.sort_data[_g]['price'] = new Array();
		}
		this.sort_data[_g].price.push( _i );

	return true;
};

Store.prototype.register_item_sort=function(_itemid,_category,_date_itemid,_group) {  // 
	// force shit to be integers
	var _d = parseInt(_date_itemid);
	var _g = parseInt(_group);
	var _i = _itemid;  // item_id+s+serial

  if (_g == 2) {
    _category = 'rods';
    _g = 1;
  }
	

	if (!isArray(this.sort_data[_g][_category])) 
	{
		this.sort_data[_g][_category] = new Array();
		if(_category == "scion"){
			this.sort_data[_g]["scionxd"] = new Array();
			this.sort_data[_g]["sciontc"] = new Array();	
		}
	}
	
	//this.debug.write('i:'+_i+' >> cat:'+_category);
	
	if ( isObject(this.sort_data[_g][_category]) )
	{
		// set the sort order for cetegory
    	this.sort_data[_g][_category].push( _i );	
		
		if(_category == "scion"){
			this.sort_data[_g]["scionxd"].push( _i );	
			this.sort_data[_g]["sciontc"].push( _i );	
			
		}
	}
	else 
	{
		alert('sort_data for g:'+_g+' cat:'+_category+' does not exist');
	}
	
		// set the sort order for date
		if (!isArray(this.sort_data[_g]['date'])) 
		{
			this.sort_data[_g]['date'] = new Array();
		}
		this.sort_data[_g].date.push( _d );
		
	return true;
};

Store.prototype.sort_item_shelves=function(_sortType,_group, redisplay) {
  if ( (this.currentTab == _sortType) && (redisplay == undefined) ) {
    return;
  }

  /* stupid hack for tabs */
  var tab_swap = this.getTabName(this.currentTab);
  /* unselect */
  this.shiftSprite(tab_swap, 'remove');

//  this.initSortBy();

  var newTab = _sortType;

  if (storeid == 7) {
    var i = _sortType.indexOf(',');

    newTab = _sortType.substring(0,i);
    _sortType = _sortType.substring(i+1);

    if (newTab == 'hair') {
      _group = 4;
    }  else {
      _group = 5;
    }
	
    if ( (newTab == this.currentTab) && 
         (_sortType == this.color_sort) &&
         (redisplay == undefined) ) {
      return;
    }

    /* <3 legacy crap */
    if (_sortType == 'all') {
      _sortType = 'price';
    }
  }
   if (storeid == 16) {  
    var i = _sortType.indexOf(',');

    newTab = _sortType.substring(0,i);
    _sortType = _sortType.substring(i+1);

	switch(newTab) {
		  case 'color':
			_group=7;
			break;
		  case 'side':
			_group=8;
			break;
		  case 'front':
			_group=9;
			break;
		  case 'roof':
			_group=10;
			break;
		  case 'bottom':
			_group=11;
			 break;
		  case 'full':
			_group=12;
			 break;
		case 'tire':
			_group=13;
			 break;
		case 'model':
			_group=14;
			 break;
	}

    if ( (newTab == this.currentTab) && 
         (_sortType == this.color_sort) &&
         (redisplay == undefined) ) {
      return;
    }

    /* <3 legacy crap */
    if (_sortType == 'all') {
      _sortType = 'price';
    }
  }

  /* select */
  tab_swap = this.getTabName(newTab);
  this.shiftSprite(tab_swap, 'add');

	// note: items should be sorted by price by default.
	//this.debug.write('sorting shelves:'+_sortType+' group:'+_group);

	// force shit to be integers
	var _g = parseInt(_group);
  groupId = _g;

	// initialize / clear the shelf array
	this.shelf_data[_g]= new Array();
	
	// get the data to put on shelves.
	if (_sortType=='new') {
		if (!isArray(this.sort_data[_g].date))
		{
			var item_array = new Array();
			//alert('Sorry, there are no '+_sortType+' items to display');
			//return;
		} else {
			var item_array = this.sort_data[_g].date.slice(0,group_data[_g].num_slots);
		}
	} 
	else if (!isArray(this.sort_data[_g][_sortType]))
	{
		//alert('Sorry, there are no '+_sortType+' items to display');
		var item_array = new Array();
		//return;
	} else {
		var item_array = this.sort_data[_g][_sortType];
	}

  if (group_data[_g].current_page != undefined) {
    this.tab_page_num[this.currentTab] = group_data[_g].current_page;
  }

/* render pagination */
  var num_items = item_array.length;
  var num_per_page = group_data[groupId].num_slots;

  var nav_page = 0;

  if (num_items < num_per_page) {
    Dom.setStyle(['pagination_bottom', 'pagination_top'], 'display', 'none');
  } else {
    Dom.setStyle(['pagination_bottom', 'pagination_top'], 'display', 'block');

    if (this.tab_page_num[_sortType] != undefined) {
      nav_page = this.tab_page_num[_sortType];
    }

    this.paginator.setState({rowsPerPage: num_per_page,
                             totalRecords: num_items,
                             page: nav_page + 1
                            });
    this.paginator.render();
  }
/* end pagination */

	// make sure the array for the group exists.
	if (!isArray(this.shelf_data[_g])) this.shelf_data[_g] = new Array();
	
	// loop through, and make the data happy.
	var _page = 0;
	this.shelf_data[_g][_page] = new Array();
	for(i=0; i<item_array.length; i++)   // 
	{
		// make sure the array for the page exists.
		if (!isArray(this.shelf_data[_g][_page])) this.shelf_data[_g][_page] = new Array();
		this.shelf_data[_g][_page].push(item_array[i]);
		
		// reset the page when we're supposed to go to the next.
		if ( ((i+1)%group_data[_g].num_slots)==0 ) 
		{	
			_page++;
		}
	}
	
	group_data[_g].last_page = _page;
	
  this.currentTab = newTab;

  /* redisplay is set to true from a sort change, but undefined from a tab change */
  if (redisplay == undefined) {
    this.sortTab(_sortType, this.currentSortType, true);
  }

  this.show_page(nav_page,_g);

  if (redisplay == undefined) {
    shopping.updateHash();
  }
	//return true;
};

Store.prototype.get_page=function(id) {

	var i,j,k, current = this;

	setTimeout(function(){
		if (current.shelf_data[groupId]) {
			for(i=0; i <= group_data[groupId].last_page;i++)
				for(j=0; j < current.shelf_data[groupId][i].length; j++)
					if (current.shelf_data[groupId][i][j] == id) {
						k = i;
						break;
					}
			store.show_page(k,groupId);
		}
		return;
	}, 300);

}
Store.prototype.show_page=function(_page,_group, updateHash) {
	// force shit to be integers
	var _g = parseInt(_group);
    
	// figger out the gopage #
	if (_page=='next') { 

        if (group_data[_g].current_page==group_data[_g].last_page) { _gopage = 0; }
		else { _gopage = group_data[_g].current_page+1; }
	} else if (_page=='prev') { 
		if (group_data[_g].current_page==0) { _gopage = group_data[_g].last_page; }
		else { _gopage = group_data[_g].current_page-1; } 
	} else if (_page=='current') {
		_gopage = group_data[_g].current_page;
	} else if (_page=='first') {
		_gopage = 0;
	} 
	else if (typeof _page == "number")
	{
		_gopage = _page;
	}
	else{
		alert(_page+' is not valid');
		return false;
	}
	
	//this.debug.write('showing page:'+_gopage+' group:'+_group);
	////this.debug.write('shelf array:'+this.debug.var_dump(this.shelf_data[_g]));
	group_data[_g].current_page = _gopage;
  this.tab_page_num[this.currentTab] = _gopage + 1;

	var i=0;

	if ( isArray(this.shelf_data[_g][_gopage]) ) 
	{
		//this.debug.write('group: '+_group+' loop slots:'+group_data[_g].num_slots);
		for(i;i<group_data[_g].num_slots;i++)  //group_data[_g].num_slots
		{
			this.show_item_div(_g,_gopage,i);
		}
	} //else {
		//this.debug.write('page:'+_gopage+' does not exist.');
	//}

  if (updateHash == true) {
    shopping.updateHash();
  }
};

Store.prototype.show_item_div=function(_group,_page,_slot){
	
	// force shit to be integers
	var _g = parseInt(_group);
	var _p = parseInt(_page);
	var _s = parseInt(_slot);
	
	// get the div.
    var div=Dom.get("item_g1"+'_s'+_s);


       if (!div) {
               return null;
       }


	// make sure we have data to put in it.
	if(!this.shelf_data[_g][_p][_s])
	{
		div.title="";
		div.emptyText="";
		div.innerHTML="";
/*
		div.onmouseover=function(){ void(0); }
		div.onmouseout=function(){ void(0); }
		div.onclick=function(){ void(0); }
*/
	} 
	else
	{
		// get the item_id for said shelf.
		  var itemkey = parseInt(this.shelf_data[_g][_p][_s]);
		// get the item data for said item.
      var idata = this.item_data[itemkey];
		
		// populate the div with the appropriate data.

		div.title=idata.name;
        div.emptyText="";
/*		div.style.backgroundColor=defaultBgColor; */
			var _alt_text = idata.name;
			
			if ( idata.price>0 && _g==1 ) _alt_text += ', '+idata.price+' '+currency;
			if ( idata.gpass>0 && idata.price==0 && _g==1) _alt_text += ', '+idata.gpass+' Gaia Cash';

      var price = '';
      var span_class = 'gold-price';

      if ( (idata.price == 0) && (idata.gpass > 0) ) {
        span_class = 'gcash-price';
        price = idata.gpass;
      } else {
        if (currency == 'tickets') {
          span_class = 'tickets-price';
        }

        price = idata.price;
      }

			div.innerHTML = '<img src="'+thumbpath+idata.thumb+'" width=30 height=30 border=0 ' + 'alt="'+_alt_text+'" title="'+_alt_text+'" /><br/>' +
        '<span class="' + span_class + '">' + YAHOO.util.Number.format(price, {thousandsSeparator: ','}) + '</span>';
		

		if ( idata.properties.display_soulbound == 1 )
		{
			div.innerHTML = '<div class="soulbound_thumb"></div>' + div.innerHTML;	
		}
		if ( idata.properties.display_frozen == 1 )
		{
			div.innerHTML = '<div class="frozen_thumb"></div>' + div.innerHTML;	
		}

    div.setAttribute('iid', itemkey);
	}
	return div;
};

//Store.prototype.preview_item=function(_itemid,e,_serial,_group,_jswinoverride) {
Store.prototype.preview_item=function(_itemid,e,_serial,_group,_jswinoverride,isOnload) {
  return;
};

//---------------------------------------------------------------------------//
// npc message handling for all actions in the store.
//---------------------------------------------------------------------------//
Store.prototype.npc_message=function(_npctext,_type,_itemid,_serial) 
{
	//'Buy this upgrade?',14,'store.php"+link+"',event,'','"+idata.item_id+"','"+storeid+"'
	
	// force numbers to be integers
	var _i = parseInt(_itemid);
	var _t = parseInt(_type);
	var _s = parseInt(_serial);
	
	// set the background form variables.
	if (_i) {
		var itemform = this.ObjectAccessor.find( 'item_id' );
		itemform.value = _i; 
	}
	if (_s) { 
		var serialform = this.ObjectAccessor.find( 'serial' );
		serialform.value = _s; 
	}
	if (_t==5 || _t==6|| _t==7) { 
		var itemqform = this.ObjectAccessor.find( 'itemq' );
		var quantityform = this.ObjectAccessor.find( 'quantity' );
		quantityform.value = itemqform.value; 
	}
	
	// get the item data.
	if (isNumber(_i)) {
		
		if (isNumber(_s)) var itemkey = _i+'s'+_s;
		else var itemkey = _i;
		
		var idata=this.item_data[itemkey];
	}
	
	var npc_box = new Object();
	npc_box.button_buy = false;
	npc_box.button_sell = false;
	npc_box.button_cancel = false;
	npc_box.thumbnail = false;

	if (_t==0)  // thank you message
	{
		if (isObject(idata)) 
		{
			npc_box.thumbnail = true;
		}
        
        if (typeof(this.dialog[this.current_npc].quest) != "undefined"){
            var scope = this;
            window.setTimeout(function(){scope.npc_quest(0);},6000);
        }
	}
	else if (_t==1) // buy
	{
		npc_box.mode = 'buy';
		npc_box.button_buy = true;
		npc_box.button_cancel = true;
		npc_box.thumbnail = true;
		npc_box.price = idata.price;
	}
	else if (_t==2) // sell
	{
		npc_box.button_sell = true;
		npc_box.button_cancel = true;
		npc_box.thumbnail = true;
		npc_box.price = Math.floor(idata.price/2);
	}
	else if (_t==3) // buy w/ gpasss
	{
		npc_box.mode = 'gpassbuy';
		npc_box.button_gpassbuy = true;
		npc_box.button_cancel = true;
		npc_box.thumbnail = true;
		npc_box.price = idata.gpass;
	}
	else if (_t==4) // add to wishlist
	{
		npc_box.button_wishlist = true;
		npc_box.button_cancel = true;
		npc_box.thumbnail = true;
		//npc_box.price = idata.price;
	}
	else if (_t==5) // buy quantity item
	{
		npc_box.button_buyq = true;
		npc_box.button_cancel = true;
		npc_box.thumbnail = true;
		npc_box.quantity = Math.abs(parseInt(itemqform.value));
		npc_box.price = idata.price*npc_box.quantity;
	}
	else if (_t==6) // buy quantity item w/ gpasss
	{
		npc_box.button_gpassbuyq = true;
		npc_box.button_cancel = true;
		npc_box.thumbnail = true;
		npc_box.quantity = Math.abs(parseInt(itemqform.value));
		npc_box.price = idata.gpass*npc_box.quantity;
	}
	else if (_t==7) // sell quantity item
	{
		npc_box.button_sellq = true;
		npc_box.button_cancel = true;
		npc_box.thumbnail = true;
		npc_box.quantity = Math.abs(parseInt(itemqform.value));
		npc_box.price = Math.floor(idata.price/2)*npc_box.quantity;
	}
	else if (_t==8) // buy hair
	{
		npc_box.mode = 'buyh';
		npc_box.button_buy = true;
		npc_box.button_cancel = true;
		npc_box.thumbnail = true;
		npc_box.price = idata.price;
	}
	else if (_t==9) // buy hair w/ gpasss
	{
		npc_box.mode = 'gpassbuyh';
		npc_box.button_gpassbuy = true;
		npc_box.button_cancel = true;
		npc_box.thumbnail = true;
		npc_box.price = idata.gpass;
	}
	else if (_t==10) // buy item with tickets
	{
		npc_box.mode = 'ticketbuy';
		npc_box.button_ticketbuy = true;
		npc_box.button_cancel = true;
		npc_box.thumbnail = true;
		npc_box.price = idata.price;
	}
	else if (_t==11) // upgrade rod
	{
		npc_box.mode = 'upgraderod';
		npc_box.button_upgrade = true;
		npc_box.button_cancel = true;
		npc_box.thumbnail = true;
		npc_box.price = idata.price;
	}
	else if (_t==12) // buy eyes
	{
		npc_box.mode = 'buye';
		npc_box.button_buy = true;
		npc_box.button_cancel = true;
		npc_box.thumbnail = true;
		npc_box.price = idata.price;
	}
	else if (_t==13) // buy eyes w/ gpasss
	{
		npc_box.mode = 'gpassbuye';
		npc_box.button_gpassbuy = true;
		npc_box.button_cancel = true;
		npc_box.thumbnail = true;
		npc_box.price = idata.gpass;
	}
	
	// start by making the submission div.
	var submit_div = '';
	if ( npc_box.button_buy==true )
	{
		submit_div+='<img src="'+buttonpath+'btn_popup_buy.png" width="41" height="14" ';
		submit_div+='onClick="store.form_submit(\''+npc_box.mode+'\');" '; 
		submit_div+='style="cursor:hand; cursor:pointer; margin:5px;" border="0">';
	}
	else if ( npc_box.button_gpassbuy==true )
	{
		submit_div+='<img src="'+buttonpath+'button_buywithcash.png" width="88" height="14" ';
		submit_div+='onClick="store.form_submit(\''+npc_box.mode+'\');" '; 
		submit_div+='style="cursor:hand; cursor:pointer; margin:5px;" border="0">';
	}
	else if ( npc_box.button_ticketbuy==true )
	{
		submit_div+='<img src="'+buttonpath+'btn_popup_buywtix.png" width="99" height="14" ';
		submit_div+='onClick="store.form_submit(\''+npc_box.mode+'\');" '; 
		submit_div+='style="cursor:hand; cursor:pointer; margin:5px;" border="0">';
	}
	else if ( npc_box.button_wishlist==true )
	{
		submit_div+='<img src="'+buttonpath+'btn_popup_wishlist.png" width="89" height="14" ';
		//submit_div+='onClick="store.form_submit(\'wishlist\');" ';
		//submit_div+='onClick="store.npc_message(\'Saving to your Wish List...\',12, '+_itemid+');" ';
		//submit_div+='onClick="store.npc_chat('+this.owner_npc+');" ';
		
	  submit_div+='onClick="store.add_wishlist('+_itemid+');" ';
		
		
		submit_div+='style="cursor:hand; cursor:pointer; margin:5px;" border="0">';
	}
	else if ( npc_box.button_sell==true )
	{
		submit_div+='<img src="'+buttonpath+'btn_popup_sell.png" width="41" height="14" ';
		submit_div+='onClick="store.form_submit(\'sell\');" '; 
		submit_div+='style="cursor:hand; cursor:pointer; margin:5px;" border="0">';
	}
	else if ( npc_box.button_buyq==true )
	{
		submit_div+='<img src="'+buttonpath+'btn_popup_buy.png" width="41" height="14" ';
		submit_div+='onClick="store.form_submit(\'buyq\');" '; 
		submit_div+='style="cursor:hand; cursor:pointer; margin:5px;" border="0">';
	}
	else if ( npc_box.button_gpassbuyq==true )
	{
		submit_div+='<img src="'+buttonpath+'button_buywithcash.png" width="88" height="14" ';
		submit_div+='onClick="store.form_submit(\'gpassbuyq\');" '; 
		submit_div+='style="cursor:hand; cursor:pointer; margin:5px;" border="0">';
	}
	else if ( npc_box.button_sellq==true )
	{
		submit_div+='<img src="'+buttonpath+'btn_popup_sell.png" width="41" height="14" ';
		submit_div+='onClick="store.form_submit(\'sellq\');" '; 
		submit_div+='style="cursor:hand; cursor:pointer; margin:5px;" border="0">';
	} 
	else if ( npc_box.button_upgrade==true )
	{
		submit_div+='<img src="'+buttonpath+'btn_popup_upgrade.png" width="60" height="14" ';
		submit_div+='onClick="store.form_submit(\''+npc_box.mode+'\');" '; 
		submit_div+='style="cursor:hand; cursor:pointer; margin:5px;" border="0">';
	}
	if ( npc_box.button_cancel==true )
	{
		submit_div+='<img src="'+buttonpath+'btn_popup_cancel.png" width="55" height="14" ';
		submit_div+='onClick="store.hide_all();" ';
		submit_div+='style="cursor:hand; cursor:pointer; margin:5px;" border="0">';
	}
	
	// make sure we show the store owner when we buy something.
	this.show_npc(this.owner_npc);
	
	// now make the content... isn't that easy
	var content_div = '';
	//content_div += '<div id="npc-dialog-name">'+this.npc_name+':</div>';
	content_div += '<div id="npc-dialog-name">'+this.npc_data[this.owner_npc].name+':</div>';
	content_div += '<div id="npc-dialog-text">';
	if ( npc_box.thumbnail == true ) 
	{
		content_div += '<img src="'+thumbpath+idata.thumb+'" align="right" width=60 height=60 style="position:relative;" border=1 />';;
	}
	if (isObject(idata)) 
	{
	    var cheap_pluralize = (npc_box.price == 1) ? '' : 's';
		content_div += _npctext.replace('{item}',idata.name).replace('{price}',npc_box.price).replace('{quantity}',npc_box.quantity).replace('{PLURAL}', cheap_pluralize)+'</div>';
	}
	else 
	{
		content_div += _npctext+'</div>';
	}
	// now we add one plus one.
	var box_html = content_div + submit_div;
	
	// then we hide everything else.
	//this.hide_all();
	
	// and populate the npc's messsage with what we want him to say.
	var _div=this.ObjectAccessor.find("npc-dialog-contents");
	_div.innerHTML = box_html;	
	
	// then show it.
	this.show_div("npc-dialog-contents");
	this.show_div("npc-dialog");
	
};

//---------------------------------------------------------------------------//
// Handler for add to wishlist event.
//---------------------------------------------------------------------------//
Store.prototype.add_wishlist=function(_itemid)
{
	//hide other chat bubbles
	//store.hide_all();
	
	//show progress message
	var content_div = '';
	content_div += '<div id="npc-dialog-name">'+this.npc_data[this.owner_npc].name+':</div>';
	content_div += '<div id="npc-dialog-text">';
	content_div += 'Saving to your Wish List...';
	content_div += '</div>';
	
	var _div=this.ObjectAccessor.find("npc-dialog-contents");
	_div.innerHTML = content_div;	
	
	this.show_div("npc-dialog");
	this.show_div("npc-dialog-contents");
	
	//dialog_click is a function that hides all when a chat bubble is clicked, this flags it
	//so the hide all does not happen
	this.skip_dialog_click = true;
		
	//send asynchronous request
	var url = '/account/asyncaddwishlist/'+this.item_data[_itemid].wishlistnonce+'/'+_itemid;	
	var content_div = '';
	content_div += '<div id="npc-dialog-name">'+this.npc_data[this.owner_npc].name+':</div>';
	content_div += '<div id="npc-dialog-text">';

	YAHOO.util.Connect.asyncRequest('GET', url, 
									{  success: function(obj) 
										{
											var rs = YAHOO.lang.JSON.parse(obj.responseText);
																						
											content_div += rs.message;
											content_div += '</div>';
											
											_div.innerHTML = content_div;		
										},
										
										failure: function(obj) {
			                content_div += 'Could not add item to your wishlist.  Please try again.</div>.'
										}
					        }
  );
		
	this.skip_dialog_click = true;
};



//---------------------------------------------------------------------------//
// generic show a message bubble. not sure if we still use this.
//---------------------------------------------------------------------------//
Store.prototype.show_message=function(_page,e){
	
    // This is likely a post-action popup. To ensure quest messages
    // show up after this window is closed, let's set this.has_seen_quests to false
    this.has_seen_quests = false;
    
	this.hide_div('showbubble');
	if (_page == 'npc_1') {
		if (this.npc_1_count == 1) this.npc_1_count = 2;
		  else if (this.npc_1_count == 2) this.npc_1_count = 1;
		var _page = _page+'_'+this.npc_1_count;
	}
	if (_page == 'npc_2') {
		if (this.npc_2_count == 1) this.npc_2_count = 2;
		else if (this.npc_2_count == 2) this.npc_2_count = 1;
		var _page = _page+'_'+this.npc_2_count;
	}
	//var crossobj=this.ObjectAccessor.find(_page);
	//crossobj.style.visibility="visible";
	//crossobj.style.display="block";
	this.show_div(_page);
	var close_counter = close_counter + 1;
	if ( e >= 1000 ) {
		var set_count = 'store.hide_div('+close_counter+')';
		var timeoutId = window.setTimeout(set_count,e);
	} else if ( e == -1 ) {
	} else {
		var set_count = 'store.hide_div('+close_counter+')';
		var timeoutId = window.setTimeout(set_count,7000);
	}
	
};


//---------------------------------------------------------------------------//
// generic hide a div.
//---------------------------------------------------------------------------//
Store.prototype.hide_div=function(_divname)
{
	var _div=this.ObjectAccessor.find(_divname);
	if (isObject(_div)) 
	{
		if (_div.style.visibility=="visible") 
		{
			_div.style.visibility="hidden";
			_div.style.display="none";
            
            // IE6 hack for select showing above the npc chat bubble
            // A select is a windowed object in IE6 and resides outside of any 
            // z-index efforts. Workaround involves hiding the select
           if ( (_divname == 'npc-dialog') && (YAHOO.env.ua.ie == 6) ) {
                var select_element = document.getElementById('sort_by_select');
                select_element.style.display = 'inline';
            }
		}
	}
	return true;
};

//---------------------------------------------------------------------------//
// generic show a div.
//---------------------------------------------------------------------------//
Store.prototype.show_div=function(_divname)
{
	var _div=this.ObjectAccessor.find(_divname);
	if (isObject(_div)) 
	{
		if (_div.style.visibility=="hidden") {
			_div.style.visibility="visible";
			_div.style.display="block";
            
            // IE6 hack for select showing above the npc chat bubble
            // A select is a windowed object in IE6 and resides outside of any 
            // z-index efforts. Workaround involves hiding the select
            if ( (_divname == 'npc-dialog') && (YAHOO.env.ua.ie == 6) ) {
                var select_element = document.getElementById('sort_by_select');
                select_element.style.display = 'none';
            }
		} 
	} 
	return true;
};

//
// Handle dialog window clicks
//
Store.prototype.dialog_click=function()
{
    // First, check to see if there are any quest messages, and if we've shown them yet
    if (!this.has_seen_quests && this.has_dialog("quest", this.current_npc))
    {
        this.has_seen_quests = true;
        this.npc_quest(0);
        return;
    }
	
	if( this.skip_dialog_click) {
		this.skip_dialog_click = false; //reset
		return;
	}

    // Finally, if all else fails, call hide_all
    this.hide_all();
}

//---------------------------------------------------------------------------//
// Hide all divs used by shopping
//---------------------------------------------------------------------------//
Store.prototype.hide_all=function()
{
	for (_divkey in this.all_divs) 
	{
		var _divname = this.all_divs[_divkey];
		this.hide_div( _divname );
	}

  shopping.updateHash();
};

Store.prototype.form_submit=function(_mode)
{
	if (_mode)
	{
		// set the mode, and send ajax call
		document.superstore.mode.value = _mode;
		document.superstore.tab_page_sort.value = store.currentTab + ';' + group_data[groupId].current_page + ';' + store.currentSortType;
		// all stores besides salon and gold purchases
		if (_mode != 'buyh' && _mode != 'gpassbuyh' && _mode != 'buye' && _mode != 'gpassbuye' && _mode != 'buy') {			
			  document.superstore.submit();
		}
		else {   
		  // display a WIP message so user knows something is going on
		  var content_div = '';
		  if (_mode == 'buyh' || _mode == 'gpassbuyh') {		// user buying hair in salon
					content_div += '<div id="npc-dialog-name">'+this.npc_data[this.owner_npc].name+':</div>';
					content_div += '<div id="npc-dialog-text">';
                    content_div += 'Please wait while we cut your hair...';
		  }
		  else if(_mode == 'buye' || _mode == 'gpassbuye'){		// user buying eyes in salon
					content_div += '<div id="npc-dialog-name">'+this.npc_data[this.owner_npc].name+':</div>';
					content_div += '<div id="npc-dialog-text">';
                    content_div += 'Please wait while we operate on your eyes...';
		  }
		  else {	// user purchasing item with gold in shops
					content_div += 'Processing...';
		  }
		  content_div += '</div>';
		  var _div=this.ObjectAccessor.find("npc-dialog-contents");
		  _div.innerHTML = content_div;
		  this.skip_dialog_click = true;

		  // send asynchronous request
		  var _store_key = document.superstore.key.value;
		  var _item_id = document.superstore.item_id.value;
		  var _nonce = document.superstore.nonce.value;
		  var url = '/gaia/shopping.php/?key='+_store_key+'&item_id='+_item_id+'&mode='+_mode+'&nonce='+_nonce;	
		  var content_div = '';
		  content_div += '<div id="npc-dialog-name">'+this.npc_data[this.owner_npc].name+':</div>';
		  content_div += '<div id="npc-dialog-text">';
                  
		  YAHOO.util.Connect.asyncRequest('GET', url, 
						{ success: function(obj) {
							var rs = YAHOO.lang.JSON.parse(obj.responseText);																		
							content_div += rs.message;
							content_div += '</div>';
							_div.innerHTML = content_div;
							
							// update the nonce so if they want to purchase again
							//right away it wont error out with an invalid nonce
							document.superstore.nonce.value = rs.nonce;
							
							if (_mode == 'buyh' || _mode == 'buye' || _mode == 'buy') {
							  // update gold amount in the header
							  var gold_span = Dom.get('gold_amt');
							  gold_span.innerHTML = rs.user_gold;
							}
							else {
							  // update cash amount in the header
							  var cash_span = Dom.get('cash_amt');
							  cash_span.innerHTML = rs.user_cash;
							}
						  },
						  failure: function(obj) {
									alert('Request failed: Unable to save hair');
						  }
								}
							);
		  setTimeout(this.updateAvatar, 4000);
		  }
	}
};

Store.prototype.redirect=function(_url)
{
	window.location.href=_url;
};

Store.prototype.updateAvatar=function()
{
  // update the avatar in the header
  var avatar_image = Dom.get('header_avatar');
  avatar_image_src = avatar_image.src;
  var url_pieces = avatar_image_src.split('?t=');
  var time_now = new Date().getTime();
  avatar_image.src = url_pieces[0] + '?t=' + time_now;
}
	
Store.prototype.shiftSprite = function(element_id, type) {
    var el = Dom.get(element_id);
    if (el == undefined) {
      return;
    }

    if (type == 'add') {
      Dom.addClass(el, element_id + '-selected');
    } else {
      Dom.removeClass(el, element_id + '-selected');
    }
}

Store.prototype.getTabName = function(tabName) {
  var tab_map = {'date': 'all', 'price': 'all', 'rods': 'equip'};
  var tab_swap;

  if (tab_map[tabName] == undefined) {
    tab_swap = tabName;
  } else {
    tab_swap = tab_map[tabName]
  }

  tab_swap +=  '_tab';

  return tab_swap;
}

  Store.prototype.addLink = function(href, text, lid) {
  var div = document.createElement('div')
  Dom.addClass(div, 'story_link');

  var a_tag = document.createElement('a');
  a_tag.href = href;
  a_tag.innerHTML = a_tag.title = text;
  Dom.addClass(a_tag, 'story_link');

  if(lid != undefined && lid.length > 0)
      a_tag.id = lid;

  div.appendChild(a_tag);
  Dom.get('store_buttons').appendChild(div);
}

function show_message(_msg_type) {
	store.show_message(_msg_type);	
}

Store.prototype.sortTabChanged = function(el) {
  if (store.change_from_init) {
    store.change_from_init = false;
    return;
  }

  this.currentSortType = el.options[el.selectedIndex].value;

  /* back to the first page on a sort */
  group_data[groupId].current_page = 0;

  if (storeid != 7 && storeid != 16) {
    this.sortTab(this.currentTab, this.currentSortType);
  } else {
    this.sortTab(this.currentTab + ',' + this.color_sort, this.currentSortType);
  }

  shopping.updateStoreLinks();
  shopping.updateHash();
}

Store.prototype.sortTab = function(tab, sortBy, sortOnly) {
  var sortTab = tab;
  if (storeid == 7 || storeid == 16) {
    sortTab = tab.substring(tab.indexOf(',')+1);
    if (sortTab == 'all') {
      sortTab = 'price';
    }
  }

  if (this.sort_data[groupId][sortTab] == undefined) {
      return;
  }

  if (sortBy.substr(0, 4) == 'date') {
    if (sortBy.match("desc")) {
      this.sort_data[groupId][sortTab].sort(this.by_date);
    } else {
      this.sort_data[groupId][sortTab].sort(this.by_date_asc);
    }
  } else {
    if (sortBy.match("desc")) {
      this.sort_data[groupId][sortTab].sort(this.by_price_desc);
    } else {
      this.sort_data[groupId][sortTab].sort(this.by_price);
    }
  }

  /* gets called from within sort_item_shelves too */
  if (sortOnly == undefined) {
    this.sort_item_shelves(tab, groupId, true);
  }
}

Store.prototype.by_date = function(a, b) {
  //return b - a;
  return parseInt(store.item_data[b].created) - parseInt(store.item_data[a].created)
}

Store.prototype.by_date_asc = function(a, b) {
  //return a - b;
  return parseInt(store.item_data[a].created) - parseInt(store.item_data[b].created)
}

Store.prototype.by_price = function(a, b) {
//  if ( (a.price == 0) && (a.gpass > 0)) {
  if ( currency=='gpass' ) {
    return parseInt(store.item_data[a].gpass) - parseInt(store.item_data[b].gpass);
  } else {
    return parseInt(store.item_data[a].price) - parseInt(store.item_data[b].price);
  }
}

Store.prototype.by_price_desc = function(a, b) {
  if ( currency=='gpass' ) {
    return parseInt(store.item_data[b].gpass) - parseInt(store.item_data[a].gpass);
  } else {
    return parseInt(store.item_data[b].price) - parseInt(store.item_data[a].price);
  }

  return store.item_data[b].price - store.item_data[a].price;
}

Store.prototype.initSortBy = function() {
  var s = Dom.get('sort_by_select');
  var opt;
  if (s.options[s.selectedIndex].value != store.currentSortType) {
    for(var i=0; i < s.options.length; i++) {
      opt = s.options[i].value.replace(' ', '');
      if (opt == store.currentSortType) {
        s.options[i].selected = true;

        break;
      }
    }
  }
}

// EVENT HANDLERS
// moved out of inline code to comply with YUI requirements on Aug 04 2005
// rjheuser@gaiaonline.com

// magical JS storage (legacy)
var StoreStorage = {};

// re-init 'user_is_new_definitions' to an array full of "true" values (if user data is not available... assume newb)
// in case it's not already defined (by shopping app)
window.user_is_new_definitions = (typeof(window.user_is_new_definitions) == 'array') ? window.user_is_new_definitions : [true, true, true, true, true, true, true, true, true, true];

YAHOO.util.Event.onDOMReady(function() {
  shopping.init();

  store.paginator = new YAHOO.widget.Paginator({
      containers: ['pagination_top', 'pagination_bottom'],
      template: '<ul class="pagination"><li class="first">{PreviousPageLink}</li> {PageLinks} <li class="last">{NextPageLink}</li></ul>',
      previousPageLinkLabel: 'Prev',
      nextPageLinkLabel: 'Next',
      currentPageClass: 'selected',
      pageLinks: 6
  });

  store.paginator.subscribe('changeRequest', function(state) {
      store.show_page(state.page - 1, groupId, true);
      store.paginator.setState(state);
  });

  if (storeid != 7 && storeid != 16) {
    store.sort_item_shelves(StoreStorage.storeSort,groupId,true);
  } else {
    store.sort_item_shelves(StoreStorage.storeSort + ',' + store.color_sort,groupId,true);
  }

  store.make_mouseovers();

  Event.addListener('dialog_close', 'click', store.dialog_click, false, store);

  /* init store navigation left/right arrows */
  var nav_elements = ['nav_left', 'nav_right'];
  Event.addListener(nav_elements, 'click', function(e) {
    var target = Event.getTarget(e);

    if (target.id == 'nav_left') {
      store.move_navigate('down');
    } else {
      store.move_navigate('up');
    }
  });

  /* add mouseover highlight to active store nagivation arrow */
  var highlight = function(e, over) {
    var target = Event.getTarget(e);

    var active = false;

    if (Dom.hasClass(target, 'nav-disabled') == false) {
      active = true;
    }

    /* same function is used for mouseover/mouseout. over is true on mouseover. */
    if (active && over) {
      Dom.addClass(target, 'nav-highlight');
    } else {
      Dom.removeClass(target, 'nav-highlight');
    }
  }

  Event.addListener(nav_elements, 'mouseover', highlight, true);
  Event.addListener(nav_elements, 'mouseout', highlight, false);

  /* some stores have custom colored bottom rounded corners */
  var rc = Dom.getElementsByClassName('rc_bottom_left', 'div');
  if (rc != null) {
    Dom.addClass(rc, 'rc_corner_left_' + storeid);
  }

  rc = Dom.getElementsByClassName('rc_bottom_right', 'div');
  if (rc != null) {
    Dom.addClass(rc, 'rc_corner_right_' + storeid);
  }

  /* stupid IE6. :hover only works on 'a' tags... make it work for divs */
  if (YAHOO.env.ua.ie == 6) {
      Event.addListener('buy-items-group', 'mouseover', function(e) {
        var target = Event.getTarget(e);
          if (target.tagName.toLowerCase() == 'img') {
            Dom.addClass(target, 'highlight');
          }
      });

      Event.addListener('buy-items-group', 'mouseout', function(e) {
        var target = Event.getTarget(e);
          if (target.tagName.toLowerCase() == 'img') {
            Dom.removeClass(target, 'highlight');
          }
      });

      Event.addListener('store_exit', 'mouseover', function(e) {
        var target = Event.getTarget(e);
        Dom.addClass(target, 'exit_hover');
      });

      Event.addListener('store_exit', 'mouseout', function(e) {
        var target = Event.getTarget(e);
        Dom.removeClass(target, 'exit_hover');
      });
  }

  store.move_navigate('start');
});

/* taken out ouf src/yui/datasource/datasource.js */

/**
 * The static Number class provides helper functions to deal with data of type
 * Number.
 *
 * @namespace YAHOO.util
 * @requires yahoo
 * @class Number
 * @static
 */
 YAHOO.util.Number = {
 
     /**
     * Takes a native JavaScript Number and formats to string for display to user.
     *
     * @method format
     * @param nData {Number} Number.
     * @param oConfig {Object} (Optional) Optional configuration values:
     *  <dl>
     *   <dt>prefix {String}</dd>
     *   <dd>String prepended before each number, like a currency designator "$"</dd>
     *   <dt>decimalPlaces {Number}</dd>
     *   <dd>Number of decimal places to round.</dd>
     *   <dt>decimalSeparator {String}</dd>
     *   <dd>Decimal separator</dd>
     *   <dt>thousandsSeparator {String}</dd>
     *   <dd>Thousands separator</dd>
     *   <dt>suffix {String}</dd>
     *   <dd>String appended after each number, like " items" (note the space)</dd>
     *  </dl>
     * @return {String} Formatted number for display.
     */
    format : function(nData, oConfig) {
        oConfig = oConfig || {};
        
        if(!YAHOO.lang.isNumber(nData)) {
            nData *= 1;
        }

        if(YAHOO.lang.isNumber(nData)) {
            var bNegative = (nData < 0);
            var sOutput = nData + "";
            var sDecimalSeparator = (oConfig.decimalSeparator) ? oConfig.decimalSeparator : ".";
            var nDotIndex;

            // Manage decimals
            if(YAHOO.lang.isNumber(oConfig.decimalPlaces)) {
                // Round to the correct decimal place
                var nDecimalPlaces = oConfig.decimalPlaces;
                var nDecimal = Math.pow(10, nDecimalPlaces);
                sOutput = Math.round(nData*nDecimal)/nDecimal + "";
                nDotIndex = sOutput.lastIndexOf(".");

                if(nDecimalPlaces > 0) {
                    // Add the decimal separator
                    if(nDotIndex < 0) {
                        sOutput += sDecimalSeparator;
                        nDotIndex = sOutput.length-1;
                    }
                    // Replace the "."
                    else if(sDecimalSeparator !== "."){
                        sOutput = sOutput.replace(".",sDecimalSeparator);
                    }
                    // Add missing zeros
                    while((sOutput.length - 1 - nDotIndex) < nDecimalPlaces) {
                        sOutput += "0";
                    }
                }
            }
            
            // Add the thousands separator
            if(oConfig.thousandsSeparator) {
                var sThousandsSeparator = oConfig.thousandsSeparator;
                nDotIndex = sOutput.lastIndexOf(sDecimalSeparator);
                nDotIndex = (nDotIndex > -1) ? nDotIndex : sOutput.length;
                var sNewOutput = sOutput.substring(nDotIndex);
                var nCount = -1;
                for (var i=nDotIndex; i>0; i--) {
                    nCount++;
                    if ((nCount%3 === 0) && (i !== nDotIndex) && (!bNegative || (i > 1))) {
                        sNewOutput = sThousandsSeparator + sNewOutput;
                    }
                    sNewOutput = sOutput.charAt(i-1) + sNewOutput;
                }
                sOutput = sNewOutput;
            }

            // Prepend prefix
            sOutput = (oConfig.prefix) ? oConfig.prefix + sOutput : sOutput;

            // Append suffix
            sOutput = (oConfig.suffix) ? sOutput + oConfig.suffix : sOutput;

            return sOutput;
        }
        // Still not a Number, just return unaltered
        else {
            return nData;
        }
    }
 };

(function() {
    YAHOO.namespace('gaia.app');

    YAHOO.gaia.app.shopping = function() {
      var panel;
      var config;
      var centered = false;
      var last_hash;

      var a_elements;

      /* properties for current item being viewed */
      var props;
      var item;
      var displaying_qty_form = false;
      var item_only = false;

      return {
        init: function() {
          /* setup panel */
          panel = new YAHOO.widget.Panel('modal', {modal: false, fixedcenter: false, close: true, width: '380px', zIndex: 250});
          panel.beforeHideEvent.subscribe(function() { shopping.closePanel() });

          /* init app init/reinit from URL */
          setInterval(function() { shopping.queryStringInit() }, 500);

          /* handlers to show preview, handle buy/add wishlist/etc */
          Event.addListener('buy-items-group', 'click', this.handleItemClicked, false, this);

          /* buy, add to wishlist, close buttons */
          Event.addListener('item_controls', 'click', this.handleButtonClick, false, this);

                 
          function getElementsByClassName() {
              
              var node = document.getElementsByTagName("body")[0];
              
              var els = node.getElementsByTagName("li");

              for(var i=0,j=els.length; i<j; i++){
                  if(els[i].className.indexOf('tab-selected') > -1){
                      return els[i];
                  }
              }
          }

          /* tab change */
          Event.addListener('sort-button-group', 'click', this.handleTabChange, false, this);

            Event.addListener('item_toggle', 'click', function(e) {
              Event.preventDefault(e);
              this.toggleAvatarPreview();
            }, false, this);

          /* phing phan is spehshul */
          if (storeid == 23) {
            var div = document.getElementById('item_image').parentNode;

            var pa_div = document.createElement('div');
            pa_div.id = 'previewAquarium';
            pa_div.innerHTML = '<iframe height="310" width="340" src="" frameborder="0"></iframe>';

            Dom.setStyle(pa_div, 'display', 'none');
            div.appendChild(pa_div);
          }

          /* so is salon durem */
          if (storeid == 7) {
            Event.addListener('colors', 'click', this.handleColorChange, false, this);
            store.shiftSprite(store.color_sort+'_tab', 'add');
          }
		  // unfortunately sams parts is too
		  if (storeid == 16) { 
            Event.addListener('cartypes', 'click', this.handleColorChange, false, this);
            store.shiftSprite(store.color_sort+'_tab', 'add');
          }

          /* and take care of anonymous */
          if (store.user_logged_in == false) {
            var div = Dom.get('message');
            div.innerHTML = 'You must log in or <a href="/register/">register</a> to buy this item.'
          }

          /* grab all the nagivation elements */
          a_elements = YAHOO.util.Dom.getElementsByClassName('navigate_button', 'a', 'store-navigation');

          /* remove cash shop from the list */
          var i;
          for(i in a_elements) {
            if (a_elements[i].id == 'victoire') {
              break;
            }
          }

          a_elements.splice(i, 1);
        },

        handleItemClicked: function(e) {
          var target = Event.getTarget(e);

          if (target.tagName.toLowerCase() != 'div') {
            target = Dom.getAncestorByClassName(target, 'buy-item');
          }

          if (target.hasChildNodes()) {
            var iid = target.getAttribute('iid');
            this.displayItemPanel(iid);
          }
        },

        handleButtonClick: function(e) {
          Event.preventDefault(e);
          this.closePanel(true);

          var target = Event.getTarget(e);
          if (target.tagName.toLowerCase() != 'a') {
            target = Dom.getAncestorByClassName(target, 'info_button'); 
          }

          var type = target.id.replace('btn_', '');
          var type_id;

          /* all done! */
          if (type == 'close') {
            return;
          }

          if (type != 'wishlist') {
            type_id = props['purchase_type'];
          } else {
            type_id = 4;
          }

          if (type_id == null) {
            type_id = props['purchase_types'][type];
          }

          var message;
          if (props['is_qty_item'] == false) {
            message = props['messages'][type];
          } else {
            message = props['messages'][type + '_qty'];
          }

          if ( (type == 'cash') && store.gcash_frozen ) {
            message += '<br /><div class=paypal_frozen>PayPal purchases may be subject to a 7 day item freeze policy.  During this time any items bought with Gaia Cash can still be equipped, but cannot be sold or traded.<br /><br /></div><div class=paypal_frozen_clr></div>';
          }

          store.npc_message(message, type_id, props['id']);
        },

        handleColorChange: function(e) {
          var target = Event.getTarget(e);
          var color = target.id.replace('_tab', '');

          if (color == store.color_sort) {
            return;
          }

          // remove class: this.color_sort
          store.shiftSprite(store.color_sort+'_tab', 'remove');

          store.sort_item_shelves(store.currentTab+','+color,groupId);

          // add class: target color, set as this.color_sort
          store.shiftSprite(target.id, 'add');

          store.color_sort = color;
        },
		
        handleTabChange: function(e) {
              
          var target = Event.getTarget(e);
       
          if (target.tagName.toLowerCase() != 'li') {
            return;
          }

          var tab = target.id.replace('_tab', '');
          /* fishing */
          if ( (storeid == 8) && (tab == 'equip') ) {
            tab = 'rods';
          } else if (storeid == 7) {
          /* salon durem */
            tab += ',' + store.color_sort;
          } else if (storeid == 16) {
            tab += ',' + store.color_sort;
          }
			
          /* all tab */
          if (tab == 'all') {
            tab = 'price';
          }

          store.sort_item_shelves(tab,groupId);
        },


        /* update/init app status from query string */
        queryStringInit: function() {
          var history = YAHOO.util.History;
          var qs = window.location.hash;

          if (YAHOO.env.ua.ie == 6) {
            var str = window.location.href;
            qs = str.substring(str.indexOf('#'));
          }

          if (qs == last_hash) {  
            return;
          } else {
            last_hash = qs;			
          }

          if (qs.length) {
            qs = qs.substr(1);
          }

          var tps = history.getQueryStringParameter('tps', qs);
          var item = history.getQueryStringParameter('item', qs);

          if (tps != null) {       
            var reSort = false;
            tps = tps.split(';');
            
            if (tps[0] && (StoreStorage.storeSort != tps[0])) {
              var tab_swap = store.getTabName(store.currentTab);
           
              /* unselect */
              store.shiftSprite(tab_swap, 'remove');
              
              StoreStorage.storeSort = store.currentTab = tps[0];

              /* select */
              tab_swap = store.getTabName(store.currentTab);
            
              store.shiftSprite(tab_swap, 'add');

              reSort = true;
            }

            if (store.currentSortType != tps[2]) {
              store.currentSortType = tps[2];

              store.initSortBy();

              reSort = true;
            }

            if (reSort) {     
              this.updateStoreLinks();

              if (storeid != 7 && storeid != 16) {
                store.sortTab(store.currentTab, store.currentSortType);
              } else {
                store.sortTab(store.currentTab + ',' + store.color_sort, store.currentSortType);
              }
            }
			
            tps[1] = parseInt(tps[1]) - 1;
            if (group_data[groupId].current_page != tps[1]) {
              store.paginator.setPage(tps[1] + 1);
            }
          }

          if (item != null) {
            this.displayItemPanel(item);
          }
        },

        displayItemPanel: function(id) {    
          if (store.item_data[id] == undefined) {
            return;
          } else {
            item = store.item_data[id];
          }

          store.hide_div('npc-dialog');
	  // disable the npc chat bubble timer if they clicked on an item
          if (store.hide_timer_id != 0) {
	    clearTimeout(store.hide_timer_id);
            store.hide_timer_id = 0;
	  }

          props = this.getItemConfig(item);
          props['id'] = id;

          this.setItemText();
          this.setItemImage();
          this.setItemButtons();

          if (centered == false) {
            panel.center();
            centered = true;
          }

          this.updateHash(id);

          panel.render();
          panel.show();
        },

        closePanel: function(call_close) {
          this.updateHash();

          if (props['is_aquarium'] == true) {
            Dom.setStyle('previewAquarium', 'display', 'none');
          }

          if (call_close == true) {
            panel.hide();
          }

          centered = false;
        },

        setItemText: function() {
          var div = Dom.get('item_name');
          div.innerHTML = item['name'];

          div = Dom.get('item_desc');
	  // for hair and eyes in salon durem hard code the item description
	  if (storeid == 7) {
	    if (item['type'] == 'base_hair') {
	      item['desc'] = 'This item will change your hairstyle. It can\'t be taken on and off like a regular item; to change your hairstyle again, you\'ll need to visit Salon Durem.';
	    }
	    else {
	      item['desc'] = 'This item will change the look of your eyes. It can\'t be taken on and off like a regular item; to change your eyes again, you\'ll need to visit Salon Durem.';
	    }
	  }
          div.innerHTML = item['desc'];

          div = Dom.get('item_price');
          div.innerHTML = props['price'];
        },

        setItemButtons: function() {
          var btns = props['buttons'];
          for(name in btns) {
            if (btns[name] == true) {
              Dom.setStyle('btn_' + name, 'display', 'block');
            } else {
              Dom.setStyle('btn_' + name, 'display', 'none');
            }
          }

	  /* if last item detail shown was a qty item and current
	     item is an qty item as well, reset qty input to 1 */
          if (props['is_qty_item'] && (displaying_qty_form == true)) {
            Dom.get('itemq').value = 1;
          }

          if (props['is_qty_item'] && (displaying_qty_form == false)) {
            Dom.setStyle('qty_form', 'display', 'block');
            Dom.get('itemq').value = 1;
            displaying_qty_form = true;
          }

          if (!props['is_qty_item'] && (displaying_qty_form == true)) {
            Dom.setStyle('qty_form', 'display', 'none');
            displaying_qty_form = false;
          }
        },

        setItemImage: function() {
          var img = Dom.get('item_image');
          var modal = Dom.get('modal');

          if (props['preview'] == true) {
            Dom.removeClass(modal, 'no-preview');

            /* item/hair preview image */
            if (props['is_aquarium'] == false) {
              Dom.addClass(modal, 'preview');

              /* show avatar with all current items by default */
              item_only = false;
              /* reset the text */
              this.toggleAvatarPreview(true);

              var param = 'item_id';
              if (props['is_hair'] == true) {
                param = 'hair_id';
              }

              if (props['is_eyes'] == true) {
                param = 'eyes_id';
              }

              var host = 'avatarsave.gaiaonline.com';
              if (GAIA_config('main_server') != 'www.gaiaonline.com') {
                host = GAIA_config('main_server');
              }

              img.src = 'http://' + host + '/profile/inventory.php?mode=preview&u=' + userid + '&' + param + '=' + props['id'] + '&store_id=' + storeid + '&item_only=0';
              img.width = 120;
              img.height = 150;
            } else {
              /* aquarium preview */
              img.src = '';

              Dom.addClass(modal, 'aq-preview');

              Dom.setStyle('previewAquarium', 'display', 'block');
              this.buildAquariumPreview();
            }
          } else {
            /* no preview, just the item image */
            Dom.addClass(modal, 'no-preview');
            Dom.removeClass(modal, 'aq-preview');
            Dom.removeClass(modal, 'preview');

            img.src = thumbpath + item['thumb'];
            img.width = 60;
            img.height = 60;

            if (props['is_aquarium']) {
              Dom.setStyle('aquariumPreview', 'display', 'none');
            }
          }

        },

        updateHash: function(item) {
          var hash = '#?tps=' + store.currentTab + ';' + (group_data[groupId].current_page+1) + ';' + store.currentSortType;
          if (isNaN(item) == false) {
            hash += '&item=' + parseInt(item);
          }

          last_hash = hash;
          window.location.replace(hash);
        },

        buildAquariumPreview: function() {
         var $ = YAHOO.util.Short;
         var url;

         $('#previewAquarium').find('iframe').attr('src', '');

         var buildPreview = function(){
           $('#previewAquarium')
				     .fadeIn(500)
				     .find('iframe')
					   .attr('src', url);
	       };

	       $.ajax({
		         url: '/aquarium/details/'+props['id'],
		         success: function(o) {
			           o = eval(o);
			           url = ('/aquariumViewer/FishTankViewer.html?location=preview&version='+GAIA_config('cache_value')+'&type='+o.sub_type+'&item_id='+ props['id'] + '&graphicsServer=http://'+GAIA_config('graphics_server')+'/images/Gaia_Flash/aquarium/');

			           buildPreview();
		         }
	       });

        },

        /* add the #?tps= for sorting to the store links when the user changes
           the sort type */
        updateStoreLinks: function() {
          var str = '#?tps=;1;' + store.currentSortType;

          for(i in a_elements) {
            var el = a_elements[i];

            var loc = el.href.indexOf('#');
            if (loc != -1) {
              el.href = el.href.substring(0,loc);
            }

            el.href += str;
          }
        },

        formatPrice: function(type, price) {
          var amount = YAHOO.util.Number.format(price, {thousandsSeparator: ','});
          var suffix;

          switch(type) {
            case 'gcash':
              suffix = 'Gaia Cash';
            break;

            case 'tickets':
              if (price > 1) {
                suffix = 'tickets';
              } else {
                suffix = 'ticket';
              }
            break;

            default:
              suffix = 'Gold'
            break;
          }

          return '<span class="' + type + '-price">&nbsp;</span>' + amount + ' ' + suffix;
        },

        toggleAvatarPreview: function(resetText) {
          var text = Dom.get('item_toggle');
          var img = Dom.get('item_image');

          if (resetText == undefined) {
            item_only = !item_only;
          }

          if (item_only == true) {
            text.firstChild.nodeValue = "View with my items";

            img.src = img.src.replace(/item_only=\d/, 'item_only=1');
          } else {
            text.firstChild.nodeValue = "View just this item";

            if (resetText == undefined) {
              img.src = img.src.replace(/item_only=\d/, 'item_only=0');
            }
          }

        },

        getItemConfig: function(item) {
          var disabled_buttons = {
              tickets: false,
              gold: false,
              cash: false,
              wishlist: false,
              upgrade: false
          };

          var config = {
            buttons: {
              gold: true,
              cash: true,
              tickets: false,
              wishlist: true,
              upgrade: false
            },

            messages: {
              wishlist: 'Add {item} to your Wishlist?',
              upgrade: 'Upgrade to {item} for {price} gold?',
              gold: 'Buy {item} for {price} gold?',
              cash: 'Buy {item} for {price} Cash?',
              tickets: 'Pick {item} for {price} ticket{PLURAL}?',
              gold_qty: 'Buy ({quantity}x) {item} for {price} gold?',
              cash_qty: 'Buy ({quantity}x) {item} for {price} Cash?'
            },

            /* some stores only have one type (prize and joy, phin phang,
               ba bargains).  otherwise, the purchase_types below are used */
            purchase_type: null,

            /* these change depending on the store (salon durem), or type (quantity item) */
            purchase_types: { gold: 1, cash: 3 },

            price: "Pricing:<br/>\n",
            preview: false,

            is_aquarium: false,
            is_hair: false,
            is_eyes: false,
            is_qty_item: false
          };

          /* Disable gcash button if gcash is not active or item doesn't have a
             gcash price */
          if (!gpass_active || item.gpass < 1) {
            config['buttons']['cash'] = false;
          }

          /* setup the purchase price and type */
          if (currency == 'gold') {
            config['price'] += this.formatPrice('gold', item.price);

            if (item.gpass > 0) {
              config['price'] += "<br/>\n" + this.formatPrice('gcash', item.gpass);
            }
          } else if (currency == 'gpass') {
            /* cash only store, yo */
            config['buttons']['gold'] = false;

            /* thanks, zomg action pack, for this stupid rule */
            if (item.gpass > 0) {
              config['price'] += this.formatPrice('gcash', item.gpass);
            } else {
              config['price'] = '';
            }

            /* gcash purchase type */
            config['purchase_type'] = 3;

          } else if (currency == 'tickets') {
            config['price'] += this.formatPrice('tickets', item.price);

            /* ticket purchase type */
            config['purchase_type'] = 10;

            config['buttons'] = disabled_buttons;
            config['buttons']['tickets'] = true;
            config['buttons']['wishlist'] = true;
          }

          /* salon durem */
          if (storeid == 7) {
            if (item['type'] == 'base_hair') {
              config['is_hair'] = true;
              config['purchase_types'] = { gold: 8, cash: 9 };
            }
            else if (item['type'] == 'base_eyes') {
              config['is_eyes'] = true;
              config['purchase_types'] = { gold: 12, cash: 13 };
            }
          }

          /* quantity items */
          if (item['jsbuy'] == 5) {
            if (store.user_logged_in) {
              config['is_qty_item'] = true;
            }
            config['purchase_types'] = { gold: 5, cash: 6 };
          }

          /* fishing rod upgrade */
          if (item['jsbuy'] == 8) {
            config['buttons'] = disabled_buttons;
            config['buttons']['upgrade'] = true;

            config['purchase_type'] = 11;
          }
          
          /* nothing but a close button for anonymous! */
          if (store.user_logged_in == false) {
            config['buttons'] = disabled_buttons;
          }

          /* setup auto preview */
          if (store.user_logged_in == true) {
            if (item['type'].match('equip') ||
                (item['jsbuy'] == 9) ||
                (storeid == 7))  {
              config['preview'] = true;
            }

            /* preview for phin phang, except on the special tab */
            if ( (storeid == 23) && (store.currentTab != 'special') ) {
              config['preview'] = true;
              config['is_aquarium'] = true;
            }
          }

          return config;
        }

      };
    }();
}());

var shopping = YAHOO.gaia.app.shopping;
