/**
* Main Brightcove Tools for Revolution Golf
*
* REQUIRES:
*	 jQuery: http://jquery.com/
*	 BrightCove API Wrapper: http://opensource.brightcove.com/project/JavaScript-MAPI-Wrapper/
*   //not needed at the moment -->// BrightCove Utilities: http://opensource.brightcove.com/project/JavaScript-Utilities/
*
* Reference:
*   media api: http://docs.brightcove.com/en/media/
*
* AUTHOR:
*	 Matthew Murchison <mmurchison@bootsoft.com>
*/

var revCove = {
  //constants
  //using booleans for easy swapping using "!"
  ASC: false,
  DESC: true,
  KILL_DROPDOWN_SPEED: 400,

  RG_CHAPTER_NUM: 0,
  RG_CHAPTER_NAME: 1,
  RG_CHAPTER_VID: 2,

  RATINGS: {
    USER: "userRating",
    AVG: "averageRating",
    NONE: "noRating"
  },

  sortByFieldNamesMap: ["publishedDate", "playsTotal", "userRating", "averageRating"],
  sortByQueryNamesMap: ["PUBLISH_DATE", "PLAYS_TOTAL", "RATING", "AVG_RATING"],
  sortByDisplayNamesCapMap: ["PUBLISHED DATE", "MOST POPULAR", "YOUR RATING", "AVERAGE RATING"],
  sortByDisplayNamesMap: ["Published date", "Most popular", "Your rating", "Average rating"],

  cliqueUnderscoredMap: [],
  cliqueDisplayMap: [],

  tags: {
    gender: ["male", "female"],
    rounds_per_month: ["1", "2", "3-5", "5-8", "8-10", "10-15", "15-20", "20+"],
    clique: ["weekend_warrior", "single_digit", "beginner", "high_handicapper", "senior", "junior"],
    interested_in: ["full_swing", "chipping", "pitching", "green_side_bunkers",
            "fairway_bunkers", "lob_shot", "driver", "fairway_woods", "hybrids",
            "putting", "power", "working_the_ball", "situational_shots",
            "mental_game", "golf_fitness", "golf_body_and_nutrition", "course_management",
            "playing_the_game", "gamesmanship", "equipment_fitting",
            "equipment_reviews", "rules_of_golf", "keeping_stats"],
    handicap: ["0-5", "6-12", "13-20", "21-28", "29-40", "41-45"],
    handicap_goal: ["0-5", "6-12", "13-20", "21-28", "29-40", "41-45"],
    expert: ["Paul Wilson"]
  },

  defaultFields: "id,name,shortDescription,longDescription,creationDate,publishedDate,lastModifiedDate,linkURL,linkText,tags,videoStillURL,thumbnailURL,referenceId,length,economics,playsTotal,playsTrailingWeek,vipVideoId",

  customFields: "rg_grouping,content_provider,internal_ad",

  mediaApiUrl: "http://api.brightcove.com/services/library",

  debugging: false,

  //reference to base page object (for instance: membersHome)
  basePageObject: null,

  //references to video player
  player: null,
  content: null,
  exp: null,
  video: null,
  videoList: null,
  originalExperienceId: null,

  //stateful variables
  currentSortBy: 0,
  currentSortDir: true,
  currentItems: null,
  currentItemsComplete: false, //whether we've already used the webservice to grab non-brightcove data
  currentVideo: null,  //whenever this value is set, currentVideo.index must be set to this obj's index in currentItems
  currentInternalAd: null,
  currentSearch: null, //used by videoGrid.js
  currentPageNum: null,   //used by videoGrid.js
  currentPage: null,
  currentTotal: null,
  currentFavorites: null,
  currentPurchased: null,
  currentOpenDropdown: null,
  currentClique: 0,

  templateLoaded: false,
  preloadedTask: null,
  dropdownTimeout: null,
  freeContentOnly: false,
  isProduct: true,
  isChaptered: true,
  autoplay: false,
  loadFirst: false,

  playlistScroller: null,
  playlistScrollerApi: null,

  channelScroller: null,
  channelScrollerApi: null,

  userId: null,

  vipVideoId: 0,

  // Default playlist, setting retrieved from Web.config by the ViewModel
  defaultPlaylistId: null,

  //BRIGHTCOVE INIT
  initReferences: function (id) {
    this.originalExperienceId = this.originalExperienceId ? this.originalExperienceId : id;
    this.player = brightcove.getExperience(this.originalExperienceId);
    this.video = this.player.getModule(APIModules.VIDEO_PLAYER);
    this.content = this.player.getModule(APIModules.CONTENT);
    this.exp = this.player.getModule(APIModules.EXPERIENCE);
    this.content.addEventListener(BCContentEvent.VIDEO_LOAD, this.onVideoLoad);
    this.video.addEventListener(BCMediaEvent.COMPLETE, this.onVideoComplete);
    this.video.addEventListener(BCMediaEvent.BEGIN, this.onVideoBegin);
  },

  //GLOBAL EVENTS INIT
  initGlobalEvents: function () {
    $(".customDropdown").bind({
      click: function (e) {
        if (e.target.className.indexOf("jsp") == -1) {
          $(this).toggleClass("active");
          $(".customDropdown").not($(this)).removeClass("active");
          clearTimeout(revCove.dropdownTimeout);
        }
      },
      mouseleave: function () {
        revCove.currentOpenDropdown = $(this);
        revCove.dropdownTimeout = setTimeout(function () {
          revCove.currentOpenDropdown.removeClass("active");
        }, revCove.KILL_DROPDOWN_SPEED);
      }
    });

    $(".customDropdownMouseOver").bind({
      mouseenter: function () {
        $(this).toggleClass("active");
        $(".customDropdownMouseOver").not($(this)).removeClass("active");
        clearTimeout(revCove.dropdownTimeout);
      },
      mouseleave: function () {
        revCove.currentOpenDropdown = $(this);
        revCove.dropdownTimeout = setTimeout(function () {
          revCove.currentOpenDropdown.removeClass("active");
        }, revCove.KILL_DROPDOWN_SPEED);
      }
    });

    $("#searchInput").bind({
      focus: function () {
        var searchInput = $(this);
        searchInput.parents("#search").addClass("active");
        if (searchInput.val() == "Search") {
          searchInput.val("");
        }
      },
      blur: function (e) {
        var searchInput = $(this);

        //if the blur is caused by clicking on the search button, don't blur and search
        if (e.originalEvent.explicitOriginalTarget) {
          if (e.originalEvent.explicitOriginalTarget.id == "searchSubmit") {
            if (!revCove.searchIsValid(searchInput.val())) {
              searchInput.focus();
            }
          }
          else {
            searchInput.parents("#search").removeClass("active");
            if ($.trim(searchInput.val()) == "") {
              searchInput.val("Search");
            }
          }
        }
      },
      keypress: function (e) {
        if (e.which == 13) {
          e.preventDefault();
          $(this).parent().submit();
          return false;
        }
      }
    });

    $("#searchSubmit").click(function () {
      var searchInput = $(this).prev();
      if (revCove.searchIsValid(searchInput.val())) {
        $(this).parent().submit();
      }
    });

    $("#cliqueDropdown .customDropdownOptions div").click(function () {
      var displayVal = $(this).text(),
                selectedVal = parseInt($(this).attr("data-value"));

      //we want to display friendlier text than "None" on the dropdown button
      if (selectedVal == 0) {
        displayVal = "Choose Playing Level";
      }

      //if the clique changes, update
      if (selectedVal != revCove.currentClique) {
        $.cookie("clique", revCove.cliqueUnderscoredMap[selectedVal], { path: '/' });
        revCove.currentClique = selectedVal;
        revCove.updateCliqueImagery();
        revCove.updateComments();
      }

      //set the dropdown button text
      $(this).parents("#cliqueDropdown").find(".currentClique").html(displayVal);
    });
  },

  initGlobalVals: function () {
    //init clique values
    this.cliqueUnderscoredMap[0] = "default";
    this.cliqueUnderscoredMap[11] = "beginner";
    this.cliqueUnderscoredMap.push("junior");
    this.cliqueUnderscoredMap.push("high_handicapper");
    this.cliqueUnderscoredMap.push("mid_handicapper");
    this.cliqueUnderscoredMap.push("weekend_warrior");
    this.cliqueUnderscoredMap.push("senior");
    this.cliqueUnderscoredMap.push("single_digit");
    this.cliqueUnderscoredMap.push("scratch_handicapper");

    this.cliqueDisplayMap[0] = "None";
    this.cliqueDisplayMap[11] = "Beginner";
    this.cliqueDisplayMap.push("Junior");
    this.cliqueDisplayMap.push("High Handicapper");
    this.cliqueDisplayMap.push("Mid Handicapper");
    this.cliqueDisplayMap.push("Weekend Warrior");
    this.cliqueDisplayMap.push("Senior");
    this.cliqueDisplayMap.push("Single Digit");
    this.cliqueDisplayMap.push("Scratch");

    if (typeof (this.currentClique) == "string") {
      //translate current clique string to integer value
      this.currentClique = this.cliqueUnderscoredMap.indexOf(this.currentClique);

      //set current clique display
      $("#cliqueDropdown .currentClique").html(this.cliqueDisplayMap[this.currentClique] == "None"
                    ? "Choose Playing Level" : this.cliqueDisplayMap[this.currentClique]);
    }
  },

  //API REQUEST FUNCTIONS
  loadVideosBySearch: function (data) {
    if (!this.templateLoaded) {
      this.storeMe(this.loadVideosBySearch, arguments);
    }
    else {
      this.isChaptered = false;
      this.isProduct = false;
      this.channelMode = true;
      revCove.currentInternalAd = 0;

      //set data obj values
      data.data.callback = "revCove.setPlaylistFromResponse";
      data.data.custom_fields = this.customFields;

      //initiate loading screen
      this.basePageObject.startLoading();

      //text search
      if (data.type == "text") {
        // Not necessary anymore -- data.type == "text" never happens
        // BCMAPI.find("find_videos_by_text", data.data);
      }
      else {
        // Old Code:
        //BCMAPI.search(data.data);

        // NEW CODE BY GASTON
        var searchData = {
          interest: data.data.all.replace("tag:interested_in|", ""),
          userId: revCove.userId,
          sortBy: revCove.sortByQueryNamesMap[revCove.currentSortBy]
        };

        var req = $.ajax({
          type: 'POST',
          url: '/services/VideoService.svc/rest/video/searchbyinterest',
          contentType: "text/json",
          dataType: 'json',
          data: JSON.stringify(searchData)
        });

        req.success(function (response) {
          if (response.success) {
            // Set currentItemsComplete to true
            // Because the call populated all the necessary fields
            revCove.currentItemsComplete = true;
            revCove.setPlaylistFromResponse(response);
          }
          else {
            //alert(response.error);
          }
        });
        // EOF NEW CODE BY GASTON
      }
    }
  },

  loadVideosByPlaylistId: function (bcPlaylistId) {
    if (!this.templateLoaded) {
      this.storeMe(this.loadVideosByPlaylistId, arguments);
    }
    else {
      this.isChaptered = false;
      // TODO: Check this values
      this.isProduct = false;
      this.channelMode = true;
      revCove.currentInternalAd = 0;

      //initiate loading screen
      this.basePageObject.startLoading();

      var searchData = {
        playlistId: bcPlaylistId,
        userId: revCove.userId,
        sortBy: revCove.sortByQueryNamesMap[revCove.currentSortBy]
      };

      var req = $.ajax({
        type: 'POST',
        url: '/services/VideoService.svc/rest/video/searchbyplaylistid',
        contentType: "text/json",
        dataType: 'json',
        data: JSON.stringify(searchData)
      });

      req.success(function (response) {
        if (response.success) {
          // Set currentItemsComplete to true
          // Because the call populated all the necessary fields
          revCove.currentItemsComplete = true;
          revCove.setPlaylistFromResponse(response);
          membersHome.setPlaylistValues(response.playlistName);
        }
        else {
          //alert(response.error);
        }
      });
    }
  },

  // Not necessary anymore

  //    //this dynamically generates a callback specific to this call so that my
  //    //calls to get ids for "rated videos" and "favorited videos" don't get criss crossed (for instance)
  //    getVideosByIds: function (data) {
  //        //generate callback function
  //        var callback = "onVideosByIds";

  //        //if custom callback needed
  //        if (data.callbackId) {
  //            callback = callback + data.callbackId;
  //        }

  //        this[callback] = function (response) {
  //            this.basePageObject[callback](response.items);
  //        };

  //        if (data.ids && data.ids.length > 0) {
  //            //make api call
  //            BCMAPI.find("videos_by_ids", {
  //                "callback": "revCove." + callback,
  //                "video_ids": data.ids,
  //                "video_fields": data.fields || this.defaultFields
  //            });
  //        }
  //        else {
  //            this[callback]({ items: [] });
  //        }
  //    },

  //API REQUEST CALLBACKS
  onVideoLoad: function (event) {
    $('#CommentBelow').hide();
    if (revCove.autoplay) {
      revCove.video.loadVideo(event.video.id);
      revCove.autoplay = false;
    }
    else {
      revCove.video.cueVideo(event.video.id);
    }
  },

  //sets the playlist after a search response (tag search) and plays the first item in the list
  setPlaylistFromResponse: function (response) {
    revCove.currentItems = response.items;
    // Force loading details from the database
    // Because we want to show the updated user rating
    // in case the user rated the video in another page
    // and comes back to the Home page or the user switches channel

    // Not necessary anymore
    // Because data is retrived from the DB with all the details populated for each video
    // revCove.currentItemsComplete = false;
    revCove.loadFirst = true;
    revCove.sortVideos({
      field: revCove.currentSortBy,
      dir: revCove.currentSortDir,
      action: revCove.setPlaylist,
      playFirst: false,
      loading: true
    });
  },

  /* from player api doc:
  Dispatched with the media completes playback. This will only be
  fired once per piece of media (unless the media is
  loaded and completed a second time after another piece of media
  is played in between).
  */
  onVideoComplete: function (event) {
    try {
      $('#CommentBelow').show();
    } catch (ex) { }

    if (revCove.currentVideo &&
       revCove.currentVideo.index != -1 &&
       revCove.currentVideo.index < (revCove.currentItems.length - 1)) {
      //if its the internal ad, show the add to cart popup at the end of the video
      if (revCove.currentInternalAd && revCove.isProduct && revCove.currentVideo.id == revCove.currentInternalAd.id) {
        try {
          $("#addToCart").click();
        }
        catch (ex) { }
      }
      //revCove.playVideoByIndex(revCove.currentVideo.index + 1, true);
    } else if (revCove.currentVideo.internalAddId == revCove.currentVideo.id
                || revCove.currentInternalAd.id == revCove.currentVideo.id) {
      revCove.video.stop();
      try {
        $("#addToCart").click();
      }
      catch (ex) { }
    }
  },

  /* from player api doc:
  Dispatched when the media begins playing the first time, post buffer.
  This is the equivalent to the old "streamStart" and should be used
  for any tracking purposes. It will only be dispatched once for a media
  object, so not on replay (unless the media is loaded a second time
  after another piece of media is played in between).
  */
  onVideoBegin: function (event) {
    //play the internal ad if this is a paid video that you don't own
    //that isn't an internal ad
    if (revCove.currentVideo.paid && !revCove.currentVideo.owned && !revCove.currentVideo.notComplete &&
                (!revCove.currentVideo.customFields || !revCove.currentVideo.customFields.internal_ad ||
                revCove.currentVideo.customFields.internal_ad != "Yes")) {
      if (revCove.currentInternalAd) {
        revCove.playVideoByObj(revCove.currentInternalAd, true);
      }
      else if (revCove.currentVideo.internalAddId) {
        if (revCove.currentVideo.id != revCove.currentVideo.internalAddId) {
          if (revCove.currentVideo.VipVideoId && revCove.currentVideo.VipVideoId != 0)
            revCove.playVideoById(revCove.currentVideo.VipVideoId, true);
          else
            revCove.playVideoById(revCove.currentVideo.internalAddId, true);
        }
      }
      else {
        revCove.playVideoByIndex(0, true);
      }
    }
    else {
      if (revCove.currentVideo.vipVideoId && revCove.currentVideo.vipVideoId != 0) {
        revCove.playVideoById(revCove.currentVideo.vipVideoId, true);
      } else {
        revCove.playVideoById(revCove.currentVideo.VipVideoId, true);
      }
    }
  },

  //PLAYER AND PLAYLIST FUNCTIONS
  //sort player takes:
  //settings, which is
  //  {
  //      field: int,                       //required
  //      dir: revCove.ASC or revCove.DESC, //required
  //      action: func                      //required (function to call with the sorted array as a parameter)
  //      playFirst: bool                   //optional (if true, loadFirst must also be true)
  //      loading: bool                     //optional (whether the loading screen is already set)
  //  }
  sortVideos: function (settings) {
    if (this.currentItems && this.currentItems.length) {
      if (!settings.loading) {
        this.basePageObject.startLoading();
      }

      settings.action(this.sortObj({
        items: this.currentItems,
        dir: settings.dir,
        getField: function () {
          var field = settings.field;
          return function (item) {
            return item[revCove.sortByFieldNamesMap[field]];
          }
        } ()
      }));
    }
    else {
      this.setPlaylist(this.currentItems);
    }
  },

  //sort by rg grouping
  prepRGGrouping: function () {
    if (this.currentItems && this.currentItems.length) {
      this.currentItems = revCove.sortObj({
        items: this.currentItems,
        dir: this.ASC,
        getField: function (item) {
          return revCove.getRGGroupingField(item, revCove.RG_CHAPTER_NUM);
        },
        getSecondaryField: function (item) {
          return revCove.getRGGroupingField(item, revCove.RG_CHAPTER_VID);
        }
      });
    }
  },

  setPlaylist: function (items) {
    //if the current items include all the data we move on, else we need to get the rest of it via webservice
    if (revCove.currentItemsComplete) {
      revCove.currentItems = items;

      //only occurs on membersHome
      if (revCove.loadFirst) {
        if (revCove.currentItems.length > 0) {
          //set the first video in the playlist (and play if indicated)
          revCove.playVideoByObj(revCove.currentItems[0], false);
        }
        revCove.loadFirst = false;
      }

      revCove.displayPlaylist();
    }
    else {
      // This code should never run because the items should alwasy be complete
      // Now, we retrieve videos' information from the database
      // and we retrieve all the necessary values
      revCove.getVideosDetails({
        items: items,
        success: function () {
          revCove.currentItemsComplete = true;

          //only occurs on membersHome
          if (revCove.loadFirst) {
            //set the first video in the playlist (and play if indicated)
            revCove.playVideoByObj(revCove.currentItems[0], false);
            revCove.loadFirst = false;
          }
          revCove.displayPlaylist();
        },
        error: function () {
          revCove.displayPlaylist();
        },
        setNewDataTo: revCove.currentItems
      });
    }
  },

  displayPlaylist: function () {
    //if isProduct and isChaptered are still true (default) then we haven't yet checked for rggrouping (first time)
    //parseRGGrouping will parse all RG Groupings if they exist, else will return false
    if (this.currentItems && this.currentItems.length) {
      if (this.isChaptered && this.parseRGGrouping()) {
        this.prepRGGrouping();
        this.hideSort();
        this.displayChapteredPlaylist();
      }
      else {
        this.displayUnchapteredPlaylist();
      }
    }
    else {
      $("#playlist").html("no videos match the search query");
    }
    this.basePageObject.stopLoading();
  },

  displayUnchapteredPlaylist: function () {
    this.showSort();

    //fill out playlist with template
    $("#playlist").html($("#playlistTemplate").jqote({
      items: this.currentItems,
      freeOnly: this.freeContentOnly
    }));

    //update now playing
    this.updateNowPlaying(this.currentVideo.id);

    //init rating stars
    $("#playlist .playlistItemRatingStars .starsWrapper").each(function (index, obj) {
      $(obj).stars({
        callback: function () {
          var thisId = $(obj).attr("id"),
                        videoId = parseInt(thisId.substr(6));
          return function (ui, type, value) {
            if (revCove.userId) {
              $("#" + thisId).stars(value);
              revCove.updateRatingClass("#" + thisId, revCove.RATINGS.USER);

              //if its the video currently in the playlist,
              //set the rating in the video actions section as well
              if (revCove.currentVideo.id == videoId) {
                $("#videoActions #ratingNumber").html(value);
                revCove.updateRating("#rating", value);
                revCove.updateRatingClass("#rating", revCove.RATINGS.USER);
              }
              revCove.rate({ value: value, ratingSelector: "#" + thisId, videoId: videoId });
            }
            else {
              modal.openLoginModal("RATING");
              revCove.updateRating("#" + thisId, $("#" + thisId).attr("data-rating"));
            }
          }
        } ()
      });

      //set initial value
      if ($(this).attr("data-rating") != Math.round($(this).attr("data-rating"))) {
        revCove.displayPartialRating($(this));
      }
      else {
        $(obj).find(".partialRating").remove().end()
                    .data("stars").select($(this).attr("data-rating"));
      }
    });
    this.updateScroll();
    this.playlistScrollerApi.scrollToY(0);
  },

  //display currentItems as chaptered playlist (test that it exists and is chaptered before using!)
  displayChapteredPlaylist: function () {
    var numVideos = this.currentItems.length,
            numChapters = this.getRGGroupingField(this.currentItems[numVideos - 1], this.RG_CHAPTER_NUM),
            videoIndex = 0,
            rating = 0,
            numRated = 0,
            tempRate,
            chapHtmlString = "",
            isFirstInChap = true,
            templateData = {},
            isCurrentVideo = false,
            isCurrentVideoChapter = false,
            api;

    for (var i = 1; i <= numChapters; i++) {
      //reinitialize variables
      templateData = { items: [] };
      rating = 0;
      numRated = 0;
      chapHtmlString = "";
      isFirstInChap = true;
      isCurrentVideoChapter = false;

      //add to inner videos html string
      while (videoIndex < numVideos &&
                    this.getRGGroupingField(this.currentItems[videoIndex], this.RG_CHAPTER_NUM) == i) {
        if (isFirstInChap) {
          templateData.chapImage = this.currentItems[videoIndex].videoStillURL || "";
          templateData.chapId = this.currentItems[videoIndex].id;
          templateData.chapName = this.getRGGroupingField(this.currentItems[videoIndex], this.RG_CHAPTER_NAME);
          isFirstInChap = false;
        }

        //push item into array for this chapter, store its index in currentItems for triggering playback
        templateData.items.push(this.currentItems[videoIndex]);
        templateData.items[templateData.items.length - 1].currentItemsIndex = videoIndex;

        //if the video has been rated, contribute it to the average rating for the chapter
        tempRate = this.getRating(this.currentItems[videoIndex]);
        if (tempRate.rating != "0") {
          numRated++;
          rating = rating + parseInt(tempRate.rating);
        }

        isCurrentVideoChapter = isCurrentVideoChapter || this.currentItems[videoIndex].id == this.currentVideo.id;

        videoIndex++;
      }

      //set other chap values
      templateData.averageRating = numRated != 0 ? rating / numRated : 0;
      templateData.freeContentOnly = this.freeContentOnly;

      //fill in and append data (once per chapter)
      $("#playlist").append($("#chapterTemplate").jqote(templateData));
      if (isCurrentVideoChapter) {
        $(".chapVideosTop:last").click();
      }

      //init chapter rating display
      $("#ratingChap" + templateData.chapId).stars({
        disabled: true
      });

      if (templateData.averageRating != Math.round(templateData.averageRating)) {
        revCove.displayPartialRating($("#ratingChap" + templateData.chapId));
      }
      else {
        api = $("#ratingChap" + templateData.chapId).data("stars");
        $("#ratingChap" + templateData.chapId).find(".partialRating").remove();
        api.select(templateData.averageRating);
      }
    }
  },

  //takes a list of items from a brightcove api call and gets values for userRating, averageRating, owned, favorited
  //and datePublished from the database via the webservice call getDetails
  getVideosDetails: function (data) {
    alert("Don't call getVideosDetails");

    data.items = this.sortObj({
      items: data.items,
      dir: this.ASC,
      getField: function (item) {
        return item.id;
      }
    });
    $.ajax({
      type: "POST",
      contentType: "text/json",
      dataType: "json",
      url: "/services/VideoService.svc/rest/video/getDetails",
      data: JSON.stringify({
        userId: this.userId || null,
        videoIds: this.objArrayToSimpleArray(data.items, "id")
      }),
      success: function (response) {
        if (response.success) {
          for (var i = 0, max = data.items.length; i < max; i++) {
            if (response.videoListDetail[i] && response.videoListDetail[i].id == data.items[i].id) {
              data.items[i].userRating = response.videoListDetail[i].userRating;
              data.items[i].averageRating = response.videoListDetail[i].averageRating;
              data.items[i].owned = response.videoListDetail[i].owned;
              data.items[i].datePublished = response.videoListDetail[i].datePublished;
              data.items[i].internalAddId = response.videoListDetail[i].internalAddId;
              data.items[i].favorited = response.videoListDetail[i].favorited;
              data.items[i].paid = response.videoListDetail[i].paid;
              data.items[i].downloadURL = response.videoListDetail[i].downloadURL;
            } else {
              data.items.splice(i, 1);
              max = data.items.length;
              i--;
            }
          }
        }
        else {
          //alert("getvideodetails: " + response.error);
        }

        data.setNewDataTo = revCove.sortObj({
          items: data.items,
          dir: revCove.currentSortDir,
          getField: function (item) {
            return item[revCove.sortByFieldNamesMap[revCove.currentSortBy]];
          }
        });

        if (data.success) {
          data.success();
        }
      },
      error: function (jqXHR, textStatus, errorThrown) {
        //alert("getvideodetailserror: " + textStatus);
        revCove.currentItems = revCove.sortObj({
          items: data.items,
          dir: revCove.currentSortDir,
          getField: function (item) {
            return item[revCove.sortByFieldNamesMap[revCove.currentSortBy]];
          }
        });
        if (data.error) {
          data.error();
        }
      }
    });
  },

  //not the preferred function, playVideoByIndex or playVideoByObject is preferred
  playVideoById: function (id, play) {
    if (!revCove.templateLoaded) {
      revCove.storeMe(revCove.playVideoById, arguments);
    }
    else {
      revCove.autoplay = !!play;
      revCove.currentVideo = { "id": id, notComplete: true };
      revCove.playVideo(revCove.currentVideo);
    }
  },

  playVideoByIndex: function (index, play) {
    if (!this.templateLoaded) {
      this.storeMe(this.playVideoByIndex, arguments);
    }
    else {
      this.autoplay = !!play;

      if (this.currentItems[index].id) {
        OnLoadComments(this.currentItems[index].id, this.currentItems[index].vipVideoId);
      }

      this.playVideo(this.currentItems[index]);
      //We have to show the "VIP Access Only" div if the user isn't a VIP member
      changeDescriptionDiv(index);

      if (this.currentItems[index].id) {
        OnLoadComments(this.currentItems[index].id, this.currentItems[index].vipVideoId);
      }
    }
  },

  playVideoByObj: function (item, play) {
    if (!this.templateLoaded) {
      this.storeMe(this.playVideoByObj, arguments);
    }
    else {
      this.autoplay = !!play;
      this.playVideo(item);
    }
  },

  playVideo: function (item) {
    if (item.VipVideoId && item.VipVideoId != 0) {
      revCove.content.getMediaAsynch(item.VipVideoId);
    }
    else if (item.vipVideoId && item.vipVideoId != 0) {
      revCove.content.getMediaAsynch(item.vipVideoId);
    }
    else
      revCove.content.getMediaAsynch(item.id);

    // Not necessary anymore because items are always complete
    if (item.notComplete) {
      //            revCove.getVideosByIds({
      //                ids: [item.id],
      //                callbackId: "Ad"
      //            });
    }
    else {
      revCove.currentVideo = item;
      revCove.setBasePageValues(item);
      revCove.currentVideo.index = revCove.inObjArray(item, revCove.currentItems, "id");
    }
  },

  setBasePageValues: function (itemObj) {
    this.basePageObject.setValues(itemObj);
  },

  //actions specific to the video loaded
  rate: function (opts) {
    //user must be logged in to rate videos
    if (this.userId && (opts.videoId || this.currentVideo)) {
      var currentVideoId = this.currentVideo.id;
      if (currentVideoId == undefined || currentVideoId == 0) {
        if ($("#currentVideoId").length > 0)
          currentVideoId = $("#currentVideoId").text();
      }

      $.ajax({
        type: "POST",
        contentType: "text/json",
        dataType: "json",
        url: "/services/VideoService.svc/rest/video/rate",
        data: JSON.stringify({
          userId: this.userId,
          videoId: opts.videoId || currentVideoId,
          rating: opts.value
        }),
        success: function (response) {
          if (response.success) {
            for (var i = 0, max = revCove.currentItems.length; i < max; i++) {
              if (revCove.currentItems[i].id == (opts.videoId || currentVideoId)) {
                revCove.currentItems[i].userRating = opts.value;
              }
            }
          }
          else {
            modal.setText(response.error);
            modal.open();
          }
        },
        error: function (jqXHR, textStatus, errorThrown) {
          alert("rateerror: " + textStatus);
        }
      });
    }
  },

  //when main content description rating is changed, update the rating in the playlist (if unchaptered)
  updatePlaylistRate: function (value) {
    //for now only update rating in playlist if note chaptered
    if (!this.isChaptered) {
      this.updateRating("#rating" + this.currentVideo.id, value);
      this.updateRatingClass("#rating" + this.currentVideo.id, this.RATINGS.USER);
    }
  },

  updateComments: function () {
    //trigger comment handler
    // Added to Avoid problems with case mix
    var currentPageUcase = this.currentPage.toUpperCase();
    if ((currentPageUcase == "HOMEINDEX") || (currentPageUcase == "HOMEVIDEO") || (currentPageUcase == "HOMEPRODUCT") || (currentPageUcase == "HOMEPLAYLIST")) {
      // if ((this.currentPage == "HomeIndex") || (this.currentPage == "homevideo") || (this.currentPage == "homeproduct")) {
      commentsView.loadComments(this.currentVideo.id, this.currentClique, this.currentVideo.vipVideoId);
    }
  },

  updateCliqueImagery: function () {
    var clique = $.cookie("clique");
    if (!clique || clique == "") {
      clique = "default";
    }

    //set non-background clique image before applying page-specific overrides
    $("#cliqueHelpArea").attr("class", clique);

    //mirrors the logic in HtmlHelpers.cs
    if (this.currentPage == "ShoppingCartIndex") {
      clique = "shopping_cart";
    }
    else if (this.currentPage == "BrowseBrowseVideos") {
      clique = "browse_videos";
    }

    $(".bgImage").attr("class", "bgImage " + clique);
  },

  updateNowPlaying: function (id) {
    var playingEl;
    if (this.isChaptered) {
      playingEl = $("#playlist").find(".chapVideos .playing").removeClass("playing").end()
                .find("#chapVideo" + id).first().addClass("playing");
      if (!playingEl.parent().hasClass("active")) {
        playingEl.siblings(".chapVideosTop").click();
      }
    }
    else {
      playingEl = $("#playlist").find(".playing").removeClass("playing").end()
        .find("#playlistItem" + id).first().addClass("playing");
    }
    // Added by Gaston because playingEl.position() is null in some cases
    if (playingEl.position() != null) {
      revCove.playlistScrollerApi.scrollToY(playingEl.position().top);
    } else {
      revCove.playlistScrollerApi.scrollToY(0);
    }
  },

  // Update the active channel
  updateActiveChannel: function (interested_in) {
    var activeChannel = $("#channel").find(".playing").removeClass("playing").end()
                .find("#channelItem-" + interested_in).addClass("playing");
    revCove.channelScrollerApi.scrollToY(activeChannel.position().top);
  },

  updateScrollSafe: function (apiSelector, contentSelector) {
    var api = apiSelector ? $(apiSelector).data("jsp") : this.playlistScrollerApi,
            content = contentSelector || "#playlist";
    if ($(content).height() > api.getContentHeight()) {
      api.reinitialise();
    }
  },

  updateScroll: function (apiSelector, contentSelector) {
    var api = apiSelector ? $(apiSelector).data("jsp") : this.playlistScrollerApi;
    api.reinitialise();
  },

  favorite: function (add, successFunc) {
    //user must be logged in to add to favorites

    var currentVideoId = this.currentVideo.id;
    if (currentVideoId == undefined || currentVideoId == 0) {
      currentVideoId = $("#currentVideoId").text();
    }

    if (this.userId && this.currentVideo) {
      $.ajax({
        type: "POST",
        contentType: "text/json",
        dataType: "json",
        url: "/services/VideoService.svc/rest/video/favorite",
        data: JSON.stringify({
          userId: this.userId,
          videoId: currentVideoId,
          addFavorite: add
        }),
        success: function (response) {
          if (response.success) {
            revCove.basePageObject.changeFavoriteText();
            for (var i = 0, max = revCove.currentItems.length; i < max; i++) {
              if (revCove.currentItems[i].id == currentVideoId) {
                revCove.currentItems[i].favorited = add;
              }
            }
            // Added by Gaston
            if (add) {
              //revCove.currentFavorites.push({ id: revCove.currentVideo.id, productName: "" });
              // Assign the video name to avoid making another call to retrieve this value later
              revCove.currentFavorites.push({ id: revCove.currentVideo.id, productName: "", name: revCove.currentVideo.name });
            }
            else {
              // Remove the current video from the favorites array
              revCove.currentFavorites = jQuery.grep(revCove.currentFavorites, function (value) {
                return value.id != currentVideoId;
              });
            }
            if (successFunc) {
              successFunc();
            }
            // EOF Added by Gaston
          }
          else {
            modal.setText(response.error);
            modal.open();
          }
        },
        error: function (jqXHR, textStatus, errorThrown) {
          alert("favorite error: " + textStatus);
        }
      });
    } else if (!this.userId) {
      modal.openLoginModal("FAVORITES");

      $("#fbLogonHelper").unbind('click');

      $("#fbLogonHelper").click(function () {
        var channelUrl = document.location.protocol + '//' + document.location.host + '/Content/StaticPages/Channel.html';

        // Retrieve the FB App Id
        var appId = $('#FBApp').text();
        // Retrieve the appId from the Web.config file
        FB.init({ appId: appId,
          channelUrl: channelUrl,
          status: true,
          cookie: true,
          xfbml: false
        });

        FB.login(function (response) {
          if (response.session) {
            // user successfully logged in
            // Redirect to Facebook handshake

            // Set the return url value in the ReturnUrl hidden-field
            var returnUrl = "/home/video/" + revCove.currentVideo.id.toString();

            var handshakeUrl = "/Account/FacebookHandshake?code=" + response.session.session_key + "&accesstoken=" + response.session.access_token + "&returnUrl=" + returnUrl;

            $.post(handshakeUrl, function (data) {
              if (data.success) {
                modal.close();
                revCove.userId = data.userId;
                // Go to the video's page because we want to show the user the favorited video
                window.location = data.returnUrl;
                revCove.favorite(add, successFunc);
              }
            });
          } else {
            // user cancelled login
            window.location = '/account/logon';
          }
        }, { perms: 'email' });
      });

      $("#modal form").submit(function (e) {
        e.preventDefault();
        $.post(
                    "/account/ajaxlogon",
                    $(this).serialize(),
                    function (result) {
                      if (result.success) {
                        modal.close();
                        revCove.userId = result.userId;
                        // window.location = '';
                        // Go to the video's page because we want to show the user the favorited video
                        window.location = "/home/video/" + revCove.currentVideo.id.toString();
                        revCove.favorite(add, successFunc);
                      } else {
                        window.location = '/account/logon';
                      }
                    },
                "json"
                );
      });
    }
  },

  //this will help sort an array of objects based on a function that returns the proper field in the obj
  //allows sorting by a secondary field (useful for RG_GROUPING sort)
  sortObj: function (opts) {
    var sorted = opts.items.sort(opts.dir == this.ASC ?
                       (opts.getSecondaryField ? sortNumAscSecondary : sortNumAsc)
                       : (opts.getSecondaryField ? sortNumDescSecondary : sortNumDesc));

    function sortNumDesc(a, b) {
      return opts.getField.call(null, b) - opts.getField.call(null, a);
    }
    function sortNumDescSecondary(a, b) {
      return (opts.getField.call(null, b) - opts.getField.call(null, a))
                        || (opts.getSecondaryField.call(null, b) - opts.getSecondaryField.call(null, a));
    }
    function sortNumAsc(a, b) {
      return opts.getField.call(null, a) - opts.getField.call(null, b);
    }
    function sortNumAscSecondary(a, b) {
      return (opts.getField.call(null, a) - opts.getField.call(null, b))
                        || (opts.getSecondaryField.call(null, a) - opts.getSecondaryField.call(null, b));
    }

    //opts.callback will optionally be called on the sorted obj array
    if (opts.callback) {
      opts.callback(sorted);
    }

    return sorted;
  },

  //utility functions
  formatTime: function (time) {
    var t_secs = Math.round(time / 1000),
            mins = Math.floor(t_secs / 60),
            secs = t_secs - (mins * 60);
    if (secs.toString().length == 1) {
      secs = "0" + secs;
    }
    return mins + ":" + secs;
  },

  //takes a function and an arguments obj and stores an anonymous function
  //that calls the passed function and parameters in the preloadedTask obj
  storeMe: function (func, args) {
    this.preloadedTask = function () {
      func.apply(this, args);
    };
  },

  //useful for building request urls
  getUrlFragment: function (field, value, key) {
    return "&" + field + "=" + (key ? key + ":" : "") + value;
  },

  //takes an array of objects and returns a simple array where each entry
  //is the value of one of the fields of the old object array
  objArrayToSimpleArray: function (objArray, field) {
    var newArray = [];
    for (var i = 0, max = objArray.length; i < max; i++) {
      newArray.push(objArray[i][field]);
    }
    return newArray;
  },

  capitalize: function (string) {
    return string.replace(/(^|\s)([a-z])/g, function (m, p1, p2) {
      return p1 + p2.toUpperCase();
    });
  },

  addCommas: function (numberAsString) {
    return numberAsString.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
  },

  submitOnEnterKey: function (formSelector, submitButtonSelector) {
    $(formSelector + " input, " + formSelector + " select").keypress(function (event) {
      if (event.keyCode == 13) {
        $(submitButtonSelector).click();
      }
    });
  },

  //helper function for checking if an array has an object with the same value for an attribute as the given object
  //returns index of the first case
  inObjArray: function (objOrValue, objArr, field) {
    if (objOrValue) {
      if (typeof objOrValue == "object") {
        for (var i = 0, maxI = objArr.length; i < maxI; i++) {
          if (objOrValue[field] == objArr[i][field]) {
            return i;
          }
        }
      }
      else {
        for (var j = 0, maxJ = objArr.length; j < maxJ; j++) {
          if (objOrValue == objArr[j][field]) {
            return j;
          }
        }
      }
    }
    return -1;
  },

  //check search string validity
  searchIsValid: function (text) {
    return text && $.trim(text) != "";
  },

  parseRGGrouping: function () {
    for (var i = 0, max = this.currentItems.length; i < max; i++) {
      //if there is no rg_grouping for one of the videos, the whole display will not be chaptered
      if (this.currentItems[i].customFields.rg_grouping) {
        //if coming from our backend it will already be an array, if coming from
        //brightcove, it will be a string, so parse if that is the case
        if (typeof this.currentItems[i].customFields.rg_grouping == "string") {
          this.currentItems[i].customFields.rg_grouping =
                        this.currentItems[i].customFields.rg_grouping.split("|", 3);
        }
      }
      else {
        if (this.currentItems[i].customFields.internal_ad) {
          revCove.currentInternalAd = this.currentItems.splice(i, 1)[0];
          max = this.currentItems.length;
          i--;
        }
        else {
          this.isChaptered = false;
          return false;
        }
      }
    }
    return true;
  },

  getRGGrouping: function (item) {
    return item.customFields.rg_grouping || null;
  },

  getRGGroupingField: function (item, field) {
    return item.customFields.rg_grouping[field] || null;
  },

  hideSort: function () {
    $("#sortByWrapper").hide().prev().hide();
  },

  showSort: function () {
    $("#sortByWrapper").show().prev().show();
  },

  getRating: function (item) {
    if (item) {
      return {
        rating: item.userRating || item.averageRating || "0",
        type: item.userRating ?
                        this.RATINGS.USER :
                        (item.averageRating ?
                                this.RATINGS.AVG :
                                this.RATINGS.NONE)
      };
    }
    else {
      return null;
    }
  },

  updateRatingClass: function (selector, setToType) {
    var r = $(selector);
    if (setToType != "averageRating") {
      r.find(".partialRating").remove();
    }
    for (var t in this.RATINGS) {
      if (this.RATINGS.hasOwnProperty(t)) {
        if (setToType == this.RATINGS[t]) {
          r.addClass(this.RATINGS[t]);
        }
        else {
          r.removeClass(this.RATINGS[t]);
        }
      }
    }
  },

  updateRating: function (selector, rating) {
    //currently we can only do full star values,
    //partial star values will come at a later release
    var stars = $(selector).data("stars");
    if (stars) {
      $(selector).find(".partialRating").remove();
      stars.select(Math.round(rating).toString());
    }
  },

  scrollToTop: function () {
    $('html, body').animate({
      scrollTop: 0
    }, 600);
  },

  displayPartialRating: function (obj) {
    if (obj.find(".partialRating").length == 0) {
      obj.append($("<div></div>")
                .addClass("partialRating")
                .css({
                  width: obj.attr("data-rating") / 5 * 60
                }));
    }
  }
};

$(document).ready(function () {
  revCove.initGlobalEvents();
  revCove.initGlobalVals();
});

//initialization scripts
// Not necessary anymore because we don't use BCMAPI anymore
// BCMAPI.token = "kmEGlT03p3pl4EQlDXH3BKeq77MIyG91fBTiaolnMywCMyj7b-z0bw..";

function onTemplateLoaded(id) {
  revCove.initReferences(id);
  revCove.templateLoaded = true;

  //if any tasks were attempted before the player is loaded,
  //the most recent is stored as a function in preloadedTask
  if (revCove.preloadedTask) {
    revCove.preloadedTask();
  }
}

//short plugin
$.fn.serializeObject = function () {
  var o = {},
        a = this.serializeArray();
  $.each(a, function () {
    if (o[this.name]) {
      if (!o[this.name].push) {
        o[this.name] = [o[this.name]];
      }
      o[this.name].push(this.value || '');
    } else {
      o[this.name] = this.value || '';
    }
  });
  return o;
};

//fix indexOf for ie
if (!Array.indexOf) {
  Array.prototype.indexOf = function (obj) {
    for (var i = 0, max = this.length; i < max; i++) {
      if (this[i] == obj) {
        return i;
      }
    }
    return -1;
  }
}
