(function ($) {

  /**
   * Load required libraries
   */
  bam.loadSync(bam.homePath + 'bam.datetime.js');
  bam.loadSync(bam.homePath + 'bam.url.js');


  var debug = false,
      uniqueDateRegExp = /^\d{2}(\d{2})-(0[1-9]|1[0-2])-(0[1-9]|[1-3]\d)T\d{2}:\d{2}:\d{2}$/;


  function getStartOfCurrentMonth (date) {
    return new Date(date.getFullYear(), date.getMonth(), 1);
  }

  function getStartOfNextMonth (date) {
    return new Date(date.getFullYear(), date.getMonth() + 1, 1);
  }

  function getEndOfPreviousMonth (date) {
    return new Date(getStartOfCurrentMonth(date).getTime() - 1);
  }
  
  function getEndOfCurrentMonth (date) {
    return getEndOfPreviousMonth(getStartOfNextMonth(date));
  };


  // Init onDOMReady
  $(function () {


    /**
     * Shortcut common libs
     */
    var DT      = bam.datetime,
        URL     = bam.url,

        /**
         * Detect IE6 to prevent see-through forms
         */
        isIE    = !+"\v1",
        isIE6   = /MSIE 6\.0/.test(window.navigator.userAgent),

        /**
         * URL fragment identifiers, used for bookmarkable dates and teams
         */
        qs      = URL.parseQueryParameters(),
        params  = URL.parseFragmentIdentifiers();

    params.month = params.month || qs.month;
    params.year  = params.year || qs.year;
    
    if (qs.c_id) {
      for (var teamId in clubProps) {
        if (clubProps[teamId].club === qs.c_id) {
          params.team_id = teamId;
          break;
        }
      }
    }


    /**
     * Set selectedDate as first day of specified month or today
     */
    var selectedDate = (params.month && params.year) ? new Date([params.month, 1, params.year].join('/')) : new Date(),
        
        // All queries before cutoverDate are passed to old transaction page
        cutoverDate = new Date(2009, 3, 1),

        // Hash object for caching transaction lookups
        transactionsCache = {},

        // Hash object for rendered transaction lists
        elementsCache = {},
        
        // DOM elements
        dataContainer = $('#transactionsContainer'),
        loadingMask   = $('#transactionsLoadingMask'),
        monthSelector = $('#transactionsDateSelector'),
        pageTitle     = $('.mcTitle');


    function renderTransactionsTable (rows) {

      var row,
          showDate,
          lastDate,
          className,
          table,
          thead,
          tr,
          th,
          tbody,
          i, n,
          td,
          span;

      table = document.createElement('TABLE');
      table.setAttribute('cellSpacing', '0');

      thead = document.createElement('THEAD');
      table.appendChild(thead);

      tr = document.createElement('TR');
      thead.appendChild(tr);

      th = document.createElement('TH');
      th.className = 'date';
      th.appendChild(document.createTextNode('Date'));
      tr.appendChild(th);

      th = document.createElement('TH');
      th.className = 'note';
      th.appendChild(document.createTextNode('Transaction'));
      tr.appendChild(th);

      tbody = document.createElement('TBODY');
      table.appendChild(tbody);

      for (i = 0, n = rows.length; i < n; ++i) {

        row       = rows[i];
        showDate  = row.date !== lastDate;
        lastDate  = row.date;
        className = (i % 2 ? 'even' : 'odd') + (showDate && i ? ' first' : '');

        tr = document.createElement('TR');
        tr.className = className;

        td = document.createElement('TD');
        td.className = 'date';
        tr.appendChild(td);
        
        if (showDate) {
          span = document.createElement('SPAN');
          span.appendChild(document.createTextNode(row.date));
          td.appendChild(span);
        }

        td = document.createElement('TD');
        td.className = 'note';
        tr.appendChild(td);

        span = document.createElement('SPAN');
        span.innerHTML = row.note;
        td.appendChild(span);

        tbody.appendChild(tr);
      };

      return table;
    };


    function sortByTransDate (a, b) {
      return (a.trans_date == b.trans_date) ? 0 : (a.trans_date > b.trans_date) ? -1 : 1;
    }

    /**
     * Merges transaction data rows on transaction ID, removes unnecessary
     * data, adds links to players and teams, and wraps data into a lookup
     * service/data grid compatible interface
     * @param {Array} rows Array of transaction data objects from lookup
     * @returns {Object} Sanitized data wrapped in data grid compatible object
     */
    function sanitizeTransactionsData (rows) {

      // Sort transaction by trans_date descending
      rows.sort(sortByTransDate);

      /**
       * Merge duplicate transaction rows
       */
      var uniqueTransactions = {},
          i, n,
          row,
          transaction,
          transactionRows = [],
          uniqueId,
          unique, 
          teams,
          players,
          teamId,
          teamName,
          teamLink,
          playerId,
          playerName,
          playerLink;

      for (i = 0, n = rows.length; i < n; ++i) {

        row = rows[i];

        if (row.note === '') {
          continue;
        }

        /**
         * Create a new unique transaction
         */
        if (!uniqueTransactions[row.transaction_id]) {
          uniqueTransactions[row.transaction_id] = {
            id:         row.transaction_id,
            date:       row.trans_date,
            type:       row.type,
            note:       row.note,
            teams:      {},
            players:    {}
          };
        }

        transaction = uniqueTransactions[row.transaction_id];

        /**
         * Append team to transaction teams hash
         */
        if (row.team !== '' && row.team_id !== '' && !transaction.teams[row.team_id]) {
          transaction.teams[row.team_id] = row.team;
        }

        /**
        * Append from_team to transaction teams hash
         */
        if (row.from_team !== '' && row.from_team_id !== '' && !transaction.teams[row.from_team_id]) {
          transaction.teams[row.from_team_id] = row.from_team;
        }

        /**
        * Append player to transaction players hash
         */
        if (row.player !== '' && row.player_id !== '' && !transaction.teams[row.player_id]) {
          transaction.players[row.player_id] = row.player;
        }

        // Cleanup
        delete rows[i];
      }

      /**
       * Enhance data for display
       */
      for (uniqueId in uniqueTransactions) {
        
        if (uniqueTransactions.hasOwnProperty(uniqueId)) {

          unique  = uniqueTransactions[uniqueId];
          teams   = unique.teams;
          players = unique.players;

          /**
           * Wrap team names with links to team pages
           */
          for (teamId in teams) {
            if (teams.hasOwnProperty(teamId)) {
              if (clubProps[teamId] !== undefined) {
                teamName = teams[teamId];
                teamLink = '<a href="http://mlb.mlb.com/index.jsp?c_id=' + clubProps[teamId].club + '">' + teamName + '</a>';
                unique.note = unique.note.replace(teamName, teamLink, 'g');
              }
            }
          }

          /**
           * Wrap player names with links to player pages
           */
          for (playerId in players) {
            if (players.hasOwnProperty(playerId)) {
              playerName = players[playerId];
              playerLink = '<a href="http://mlb.mlb.com/team/player.jsp?player_id=' + playerId + '">' + playerName + '</a>';
              unique.note = unique.note.replace(playerName, playerLink, 'g');
            }
          }

          transactionRows.push({
            date: unique.date.replace(uniqueDateRegExp, '$2/$3/$1'),
            note: unique.note
          });

          // Cleanup
          delete uniqueTransactions[uniqueId];
        }
        
      }

      return transactionRows;
    };


    /**
     *
     */
    function showLoadingMask () {

      /**
       * Hide selector in IE to avoid rendering bug where form elements show
       * through loading mask
       */
      if (isIE6) {
        monthSelector.css('visibility', 'hidden');
      }

      // Show loading mask
      loadingMask.show();
    };


    /**
     *
     */
    function hideLoadingMask () {

      // Hide loading mask
      loadingMask.hide();

      // Show selector in IE
      if (isIE6) {
        monthSelector.css('visibility', 'visible');
      }
    };


    /**
     * Main routine with a silly name
     * @param {Number} month
     * @param {Number} year
     * @param {Number} teamId Unique team ID
     */
    function playYoPartThreeStacks (month, year, teamId) {

      var date = new Date([month, 1, year].join('/'));

      /**
       * Handle requests before cutover date
       */
      if (date < cutoverDate && !debug) {
        var url = '?';
        if (teamId) {
          url += 'c_id=' + clubProps[teamId].club + '&';
        }
        url += 'year=' + year + '&month=' + month;
        window.location.href = url;
        return;
      }

      /**
       * Calculate query date parameters and convert to YYYYMMDD format
       */
      var startDate = DT.toYMD(date),
          endDate   = DT.toYMD(getEndOfCurrentMonth(date));

      /**
       * Set cache key using start and end dates and team ID
       */
      var cacheKey = startDate + '-' + endDate;
      if (teamId) {
        cacheKey += '-' + teamId;
      }


      /**
       * Load data from service
       */
      if (elementsCache[cacheKey]) {
        dataContainer.html(elementsCache[cacheKey]);
      } else {


        showLoadingMask();


        /**
         * Use setTimeout to workaround IE rendering bug which fails to show
         * loading mask
         */
        window.setTimeout(function () {

          /**
           * Assemble lookup URL
           */
          var url = [
            '/lookup/json/named.transaction_all.bam',
            '?start_date=', startDate,
            '&end_date=', endDate
          ].join('');

          // Add team ID
          if (teamId) {
            url += '&team_id=' + teamId;
          } else {
            url += '&sport_code=\'mlb\'';
          }

          /**
           * Load transaction data from lookup service
           */
          $.ajax({
            url:      url,
            async:    true,
            dataType: 'json',

            /**
             * Handle successful lookup response
             */
            success: function (data) {
              // Simplify transactions data
              var rows = bam.util.getQueryResults(data, 'transaction_all');

              if (rows.length > 0) {

                // Add data to cache
                transactionsCache[cacheKey] = sanitizeTransactionsData(rows);

                // Refresh display with returned data
                elementsCache[cacheKey] = renderTransactionsTable(transactionsCache[cacheKey]);

              } else {

                // No results message
                var em = document.createElement('EM');
                em.appendChild(document.createTextNode('No transactions found.'));
                elementsCache[cacheKey] = em;

              }

              dataContainer.html(elementsCache[cacheKey]);

              hideLoadingMask();
            },

            /**
             * Handle potential lookup errors
             */
            error: function () {
              window.alert('Unable to retreive data.');

              hideLoadingMask();
            }

          });

        }, 0);

      }

      // Update title
      var text = (teamId) ? clubProps[teamId].club_full_name : 'Major League Baseball';
      pageTitle.text(text + ' Transactions');

      // Update stored parameters and window.location
      params.month = month;
      params.year  = year;

      /**
       * Replace page location with bookmarkable URL
       */
      var frags = '#month=' + month + '&year=' + year;

      if (teamId) {
        params.team_id = teamId;
        frags += '&team_id=' + teamId;
      }

      window.location.replace(frags);
    };


    function sortByClubFullName (a, b) {
      return (a.club_full_name == b.club_full_name) ? 0 : (a.club_full_name < b.club_full_name) ? -1 : 1;
    }
    
    function renderTeamLinks () {

      var teams = [],
          teamId,
          ul,
          li,
          a,
          strong,
          i, n,
          team;

      for (teamId in clubProps) {
        if (clubProps[teamId].team_id !== 'undefined') {
          teams.push(clubProps[teamId]);
        }
      }

      teams.sort(sortByClubFullName);

      ul = document.createElement('UL');

      li = document.createElement('LI');
      ul.appendChild(li);

      a = document.createElement('A');
      a.href = 'index2.jsp#';
      a.className = 'textSm';
      li.appendChild(a);

      strong = document.createElement('STRONG');
      strong.appendChild(document.createTextNode('View all transactions'));
      a.appendChild(strong);

      for (i = 0, n = teams.length; i < n; ++i) {

        team = teams[i];

        li = document.createElement('LI');
        ul.appendChild(li);

        a = document.createElement('A');
        a.href = 'index2.jsp#team_id=' + team.team_id;
        a.className = 'textSm';
        a.appendChild(document.createTextNode(team.club_full_name));
        li.appendChild(a);
      };

      return ul;
    };
    






    /**
     * Add team navigation to left nav if page has element: transactions_teams
     * (only on /mlb/transactions)
     */
    var transactionsTeams = $('#transactions_teams');

    if (transactionsTeams.size() > 0) {
      transactionsTeams.html(renderTeamLinks());

      /**
       * Initialize team links
       */
      transactionsTeams.find('a').click(function (e) {
        // Prevent default to avoid unnecessary location update
        e.preventDefault();
        var frags = URL.parseFragmentIdentifiers(this.href);
        playYoPartThreeStacks(params.month, params.year, frags.team_id);
      });
    }






    /**
     * Initialize date selector
     */
    monthSelector.monthSelector({
      selectedDate: selectedDate,
      minDate:   '1/1/2001',
      firstText: '<span class="icon">&laquo;</span>',
      lastText:  '<span class="icon">&raquo;</span>',
      prevText:  '<span class="icon">&lt;</span>',
      nextText:  '<span class="icon">&gt;</span>',
      callback: function (date) {
        var month = date.getMonth() + 1,
            year  = date.getFullYear();
        playYoPartThreeStacks(month, year, params.team_id);
      }
    });
  });

})(jQuery);

