/*
* namco-ui.js --
*   Common widget functionality
*/

/*
  Feature switcher: 4-game switcher with fading side or bottom info bar
*/

var Switcher = function(args) {
  var currentlySelectedThumb = 0;
  
  // Assign side thumbnails/links
  for (i = 1; i <= 4; i++) {
    var thumb = $("#featurethumb" + i);
    var thumbLink = thumb.find("a");
    var thumbImg = thumbLink.find("img");
    var array = args[i];
    var thumbImgURL = array.thumbnailImgURL;
    var headlineImgURL = array.headlineImgURL;
    var alt = array.alt;
    var url = array.url;
    
    // Replace with 'unknown' image if thumbnail/headline img url is blank
    var imgPattern = /(?:([^:\/?#]+):)?(?:\/\/([^\/?#]*))?([^?#]*\.(?:jpg|gif|png))(?:\?([^#]*))?(?:#(.*))?/
    
    if (!thumbImgURL.match(imgPattern))
      thumbImgURL = "/images/switcher_unknown_thumb.png";
    if (!headlineImgURL.match(imgPattern))
      headlineImgURL = "/images/switcher_unknown.png";
    
    $(thumbLink).attr({href: url});
    $(thumbImg).attr({
      src: thumbImgURL,
      alt: alt,
      title: alt
    });
  }
  
  // For IE6, Remove <img> and switch to a css bg to fix thumb height issue
  if ($.browser.msie && $.browser.version < 7)
    $(".featurethumb").each(function() {
      var imgURL = $(this).find("img").attr("src");
      $(this).html("");
      $(this).css({backgroundImage: "url(" + imgURL + ")"});
    });
  
  // Elements are hidden by default; make visible
  $("#featurethumbs, #sideinfo, #bottominfo").css({visibility: "visible"});
  
  var showFeature = function(featureIndex) {
    // Extract data for switcher from args class parms
    var array = args[featureIndex];
    var featureHeadlineImgURL = array.headlineImgURL;
    var featureTitle = array.title;
    var featureDescription = array.desc;
    var infoLocation = array.infoLocation;
    var targetURL = array.url;
    
    if (currentlySelectedThumb != featureIndex) {
      var previouslySelectedThumb = currentlySelectedThumb;
      
      // Kill any current animations happening from an incomplete hover event
      $("#featurestabs .info").stop();
      
      // Reset the previous thumbnail thumbnail with a border enabled
      if (previouslySelectedThumb > 0)
        $("#featurestabs #featurethumb" + previouslySelectedThumb).removeClass("selected");
      
      // Update our global to indicate that this is the selected thumbnail
      currentlySelectedThumb = featureIndex;
      
      // Change main feature bg image and update side info bar
      $("#featurestabs").css({backgroundImage: "url(" + featureHeadlineImgURL + ")"});
      
      // Set thumbnail border
      $("#featurestabs #featurethumb" + featureIndex).addClass("selected");
      
      // Fade out the info bar; replace info data and fade in new info bar
      $("#featurestabs .info").fadeTo(150, 0, function() {
        var info = $("#featurestabs #" + infoLocation + "info");
        info.find(".featuretitle").html("<a href=\"" + targetURL + "\">" + featureTitle + "</a>");
        info.find(".featuredesc").html(featureDescription);
        info.find(".featuredesc").append(
          "<a href=\"" + targetURL + "\"><p class=\"playnow\">LEARN MORE</p></a>"
        );
        info.fadeTo(150, 0.8, function() {
          info.find(".featuretitle").fadeTo(100, 0.8);
          info.find(".featuredesc").fadeTo(100, 0.8);
        });
      });
      
      // Go to game page if bg image is clicked
      $("#featurestabs").click(function() {
        window.location.href = targetURL;
      });
    }
  };
  
  /*
    Preload images before display; as a callback, assign click/hover to all elements
  */
  var preload = function(callback) {
    for (i = 1; i <= 4; i++) {
      var image = new Image();
      image.src = args[i].headlineImgURL;
    }
    
    callback();
  };
  
  // Used for events that stop the timer before displaying the selected feature
  var activateFeature = function(id) {
    if (this.autoCycle)
      clearInterval(this.autoCycle);
    
    showFeature(id);
  };
  
  /* Used for events that will reactivate the timer (such as a mouseout)--
      will restart the timer after the specified start interval */
  var activateInterval = function() {
    if (args.autoCycleInterval > 0) {
      this.autoCycle = setInterval(function() {
        if (currentlySelectedThumb < 4)
          next_index = currentlySelectedThumb + 1;
        else
          next_index = 1;
        
        showFeature(next_index);
      }, args.autoCycleInterval);
    }
  };
  
  preload(function() {
    // Show first item in list, activate feature auto-cycle
    showFeature(1);
    activateInterval();
    
    /*
      Create mouse over/out events for 4 thumbnails, which stops/starts the auto-cycle, respectively;
      if the user is on an iPhone or iPad (cannot hover over images), use clicking instead of hovering
    */
    if (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i))
      use_click = true;
    else
      use_click = false;
    
    $(".featurethumb").each(function(i) {
      if (use_click)
        $(this).click(function() {
          activateFeature(i + 1);
          
          return false;
        });
      else
        $(this).hover(
          function() { activateFeature(i + 1); },
          function() { activateInterval(); }
        );
    })
  });
};

/*
  Fade-in tooltip --
    The assigned ID has the following structure:
    
      <div id="<id>" class="tooltip">
        <div class="title"></div>
        <div class="image"></div>
        <div class="desc"></div>
        <div class="genre"><p>Genre: <em class="name"></em></p></div>
      </div>
*/
var Tooltip = function(id) {
  this.title = "";
  this.thumbnail = "";
  this.desc = "";
  this.genre = "";
  this.position = [0, 0];
  this.namcoOriginal = false;
  this.event = 0;
  
  this.show = function() {
    var tooltip = $(id);
    tooltip.find(".title").html(this.title);
    tooltip.find(".desc").html(this.desc);
    
    // Create tooltip image
    var image = new Image();
    image.src = this.thumbnail;
    image.className = "image";
    tooltip.find(".image").replaceWith(image);
    
    tooltip.find(".genre .name").html(this.genre);
    
    // Position tooltip
    tooltip.css({left: this.position[0] + "px"});
    tooltip.css({top: this.position[1] + "px"});
    
    // Show/hide Namco original label
    var namcoLabel = tooltip.find(".namcooriginal");
    
    if (this.namcoOriginal == 1)
      namcoLabel.css({visibility: "visible"});
    else
      namcoLabel.css({visibility: "hidden"});
    
    // Flush any existing hover timers
    clearTimeout(this.showTimer);
    
    // Begin fadein after delay
    this.showTimer = setTimeout(function() {
      if ($.browser.msie) {
        /* Fadein for transparent tooltip bg causes display issues in IE
        (thick black halo around the edges), so don't use it with those browsers */
        tooltip.show();
      } else
        tooltip.fadeIn("fast");
    }, 500);
  };
  
  this.hide = function() {
    var tooltip = $(id);
    clearTimeout(this.showTimer);
    tooltip.hide();
  };
};

/*
  Dynamic list paginator--
    Given a div, all elements within will be automatically paginated,
    based on the # of elements allowed to be displayed at a time
*/
var Paginator = function(id, showPerPage, pagesToShow) {
  this.currentPage = 1;
  this.showPerPage = showPerPage;
  this.id = id;
  
  if (pagesToShow)
    this.pagesToShow = pagesToShow;
  else
    this.pagesToShow = 10;  // Default to showing 10 page links max (except first/last page)
  
  var children = $(id).children();
  var itemCount = children.size();
  var pageCount = Math.ceil(itemCount / showPerPage);
  var pageGroup = {start: 1, end: this.pagesToShow};
  
  

  this.show = function(pageIndex) {
    pageIndex = parseInt(pageIndex);
    
    /*
      Determine if we need to change the displayed page group --
        if on the first page, last page, or at the start/end of the current group
    */
    if (pageIndex == 1) // Is the first page
      pageGroup = {
        start: 1,
        end: this.pagesToShow
      };
    else if (pageIndex == pageCount) // Is the last page
      pageGroup = {
        start: pageIndex - this.pagesToShow,
        end: pageIndex
      };
    else if (pageIndex == pageGroup.start || pageIndex == pageGroup.end)  // Is at the beginning or end of page group
      pageGroup = {
        start: pageIndex - (this.pagesToShow / 2),
        end: pageIndex + (this.pagesToShow / 2)
      };
    
    var pager = $("#pageselector");
    this.currentPage = parseInt(pageIndex);
    
    // Clear all previously enabled elements
    children.hide();
    
    // Show relevant elements, hide those not matching current page
    for (var i = 0; i < itemCount && i < this.showPerPage; i++) {
      elementIndex = i + this.showPerPage * (this.currentPage - 1);
      
      if (elementIndex < itemCount)
        $(children[elementIndex]).css({display: "block"});
    }
    
    // Populate the page selector
    pager.html("");
    
    if (pageCount > 1)
      for (var i = 1; i <= pageCount; i++) {
        var isDisplayed = false;
        var pageLink = document.createElement("div");
        pageLink.id = "pageLink" + i;
        pageLink.className = "pagelink";
        pageLink.paginator = this;
        $(pageLink).click(function() {
          this.paginator.show($(this).find("p").html());
        })
        
        if (i == this.currentPage)
          $(pageLink).addClass("selected");
        else if ((i == 1 || i == pageCount) && pageCount >= this.pagesToShow)
          $(pageLink).addClass("endpage");
        
        pageLink.innerHTML = "<p>" + i + "</p>";
        
        if ((i >= pageGroup.start && i <= pageGroup.end) || i == pageCount || i == 1)
          pager.append(pageLink);
      }
  };
};

/*
  Genre-based game switcher --
    Retrieves games from AJAX-based resource, based on currently selected genre

  -After a request, it will store a genre's game list in memory, to prevent redundant
  requests and reduce server load.
  
  -Tooltip will be built based on hidden input data
  (see tooltip div description for required attributes)
*/
var GenreSelector = function(genreList, defaultGenre, gamesContainer, resource, gamesPerPage, tooltip) {

  var selectedGenre = defaultGenre;
  var genreDataCache = {};  // Stores previous genre request data
  var gamesContainer = $(gamesContainer);

  /*
    showGenre(callback)
    
    Send an AJAX request to the given resource,
    which is a PHP file in the following location and format:
      /resources/[resource].php?genre=[selectedGenre]
      
      i.e.,
        /resources/pc_games.php?genre=match3
      
    The PHP script's response is then injected into gamesContainer.
  */
  
  var showGenre = function(callback) {
    var doShow = function() {
      paginator = new Paginator(gamesContainer, gamesPerPage);
      paginator.show(1);

      /* Assign tooltip click events to each game,
      from a newly-instantiated Tooltip */
      var localTooltip = this.tooltip;

      var showTooltip = function(e) {
        var gameDiv = $(this).parent().parent();
        localTooltip.position = [
          gameDiv.position().left + ($(gameDiv).width() / 2),
          gameDiv.position().top + ((
            gameDiv.find(".icon").height() + $(gameDiv).find(".title").height()
          ) + 5)
        ];
        var parentNode = $($(this).parents()[1]);
        var isNamcoOriginal = parentNode.find(".is_namco_original").attr("value");
        localTooltip.desc = parentNode.find(".desc").attr("value");
        localTooltip.thumbnail = parentNode.find("img").attr("src");
        localTooltip.genre = parentNode.find(".genre").attr("value");
        localTooltip.title = parentNode.find(".title a span").html();
        
        if (isNamcoOriginal)
          localTooltip.namcoOriginal = true;
        else
          localTooltip.namcoOriginal = false; 
        
        localTooltip.show();
      }
      
      var hideTooltip = function() {
        localTooltip.hide();
      }
      
      $(gamesContainer).children().each(function() {
        $(this).find("a").hover(showTooltip, hideTooltip);
      });
      
      if (callback) callback();
    };
    
    // If the genre game data exists in our cache array, load that in place of an AJAX request
    if (genreDataCache[selectedGenre]) {
      gamesContainer.html(genreDataCache[selectedGenre]);
      doShow();
    } else {
      $.get("/resources/" + resource + ".php?genre=" + selectedGenre, function(data) {
        genreDataCache[selectedGenre] = data;
        gamesContainer.html(genreDataCache[selectedGenre]);
        doShow();
      });
    }
    
    $("#" + selectedGenre).addClass("selected");
  };
  
  /* Assign click events to each link in the genre listing;
  it will assign the object's selected genre based on the element's ID */
  $(genreList).each(function() {
    $(this).click(function() {

      var pager = $("#pageselector");
      if(this.id != selectedGenre) {
        gamesContainer.stop();
        pager.hide();
        selectedGenre = this.id;
        
        $(genreList + ".selected").each(function() { $(this).removeClass("selected"); });
        gamesContainer.fadeTo(100, 0.5, function() {  // Show loading appearance
          showGenre(function() {
            gamesContainer.fadeTo(200, 1.0);
            pager.show();
          });
        });

      } else
        return false;
    });
  });
  
  // Show default genre on load
  showGenre();
};


var GenreTooltip = function(gamesContainer,genretooltip){

  /* Assign tooltip click events to each game,
  from a newly-instantiated Tooltip */
  var gamesContainer = $(gamesContainer);
  this.genretooltip = genretooltip;
  
  var localTooltip = this.genretooltip;

  var showTooltip = function(e) {
    var gameDiv = $(this).parent().parent();
    localTooltip.position = [
      gameDiv.position().left + ($(gameDiv).width() / 2),
      gameDiv.position().top + ((
        gameDiv.find(".icon").height() + $(gameDiv).find(".title").height()
      ) + 5)
    ];
    var parentNode = $($(this).parents()[1]);
    var isNamcoOriginal = parentNode.find(".is_namco_original").attr("value");
    localTooltip.desc = parentNode.find(".desc").attr("value");
    localTooltip.thumbnail = parentNode.find("img").attr("src");
    localTooltip.genre = parentNode.find(".genre").attr("value");
    localTooltip.title = parentNode.find(".title a span").html();
    
    if (isNamcoOriginal)
      localTooltip.namcoOriginal = true;
    else
      localTooltip.namcoOriginal = false; 
    
    localTooltip.show();
  }
  
  var hideTooltip = function() {
    localTooltip.hide();
  }
  
  $(gamesContainer).children().each(function() {   
    $(this).find("a").hover(showTooltip, hideTooltip);
  });
}
/*
  Pager to flip through screenshots --
    Requires a set of:  * Selection "buttons" (.screenshotselector -> #screenshotselector[1,2,3,...])
              * Images (.screenshotimg -> #screenshotimg[1,2,3,...])
              * Back/forward arrows -> #screenshotarrowback, #screenshotarrowfwd
    
*/
var ScreenshotPager = function() {
  var pager = this;
  var pageCount = $(".screenshotimg").size();
  
  this.currentPage = 1;
  
  /* Show image; updates current page = page
      -- also sets timer to automatically flip through images */
  this.show = function(page) {
    clearInterval(this.timer);
    this.currentPage = parseInt(page);
    $(".screenshotselector").removeClass("selected");
    $(".screenshotimg").hide();
    $("#screenshotselector" + page).addClass("selected");
    $("#screenshotimg" + page).fadeIn();
    
    this.timer = setInterval(function() {
      pager.next();
    }, 5000);
  };
  
  // Go to next image; if at the end of the list, activate first image
  this.next = function() {
    if (this.currentPage < pageCount)
      this.show(this.currentPage + 1);
    else
      this.show(1);
  };
  
  // Go to previous image; if at the beginning of the list, activate last image
  this.previous = function() {
    if (this.currentPage > 1)
      this.show(this.currentPage - 1);
    else
      this.show(pageCount);
  };
  
  // Assign click events to selection buttons and back/fwd arrows
  $(document).ready(function() {
    $(".screenshotselector").click(function(){
      var pageID = parseInt($(this).find("[name=pageid]")[0].value);
      
      // Don't let user click on already selected selector button
      if (pageID != pager.currentPage)
        pager.show(pageID);
    });
    
    $("#screenshotarrowback").click(function() {
      pager.previous();
    });
    
    $("#screenshotarrowfwd").click(function() {
      pager.next();
    });
  });
  
  this.show(1);
};


/*
  Pager to flip through videos --
    Requires a set of:  * Selection "buttons" (.videoselector -> #videoselector[1,2,3,...])
              * Images (.video -> #video[1,2,3,...])
              * Back/forward arrows -> #videoarrowback, #videoarrowfwd
    
*/
var VideoPager = function() {
  var pager = this;
  var pageCount = $(".video").size();
  
  this.currentPage = 1;
  
  /* Show image; updates current page = page
      -- also sets timer to automatically flip through images */
  this.show = function(page) {
    clearInterval(this.timer);
    this.currentPage = parseInt(page);
    $(".videoselector").removeClass("selected");
    $(".video").hide();
    $("#videoselector" + page).addClass("selected");
    $("#video" + page).fadeIn();
    
    /*this.timer = setInterval(function() {
      pager.next();
    }, 5000);*/
  };
  
  // Go to next image; if at the end of the list, activate first image
  this.next = function() {
    if (this.currentPage < pageCount)
      this.show(this.currentPage + 1);
    else
      this.show(1);
  };
  
  // Go to previous image; if at the beginning of the list, activate last image
  this.previous = function() {
    if (this.currentPage > 1)
      this.show(this.currentPage - 1);
    else
      this.show(pageCount);
  };
  
  // Assign click events to selection buttons and back/fwd arrows
  $(document).ready(function() {
    $(".videoselector").click(function(){
      var pageID = parseInt($(this).find("[name=pageid]")[0].value);
      
      // Don't let user click on already selected selector button
      if (pageID != pager.currentPage)
        pager.show(pageID);
    });
    
    $("#videoarrowback").click(function() {
      pager.previous();
    });
    
    $("#videoarrowfwd").click(function() {
      pager.next();
    });
  });
  
  this.show(1);
};
