BSD.namespace('event.srp');

/*** Location Bar ***/
BSD.event.srp.locationbar = {
  editSearchDistance: function(e) {
    if(YAHOO.util.Event.getTarget(e).href) {
      BSD.event.srp.locationbar._toggleBar();
      YAHOO.util.Dom.get("search-distance-input").focus();
      YAHOO.util.Dom.get("search-distance-input").select();
      YAHOO.util.Event.stopEvent(e);
    }
  },

  editSearchLocation: function(e) {
    if(YAHOO.util.Event.getTarget(e).href) {
      BSD.event.srp.locationbar._toggleBar();
      YAHOO.util.Dom.get("search-location-input").focus();
      YAHOO.util.Dom.get("search-location-input").select();
      YAHOO.util.Event.stopEvent(e);
    }
  },

  _toggleBar: function(e) {
    var sd = YAHOO.util.Dom.get("search-distance");
    var sl = YAHOO.util.Dom.get("search-location");

    // Turn on form
    if(sd.style.display == '') {
      sd.style.display = 'none';
      sl.style.display = 'none';

      YAHOO.util.Dom.get("search-distance-input").type = "text";
      YAHOO.util.Dom.get("search-location-input").type = "text";
      YAHOO.util.Dom.get("search-submit").type = "submit";

    // Turn off form
    } else {
      sd.style.display = '';
      sl.style.display = '';

      var d = YAHOO.util.Dom.get("search-distance-input").value;
      var l = YAHOO.util.Dom.get("search-location-input").value;

      YAHOO.util.Dom.get("search-distance-input").type = "hidden";
      YAHOO.util.Dom.get("search-location-input").type = "hidden";

      // Weird FF bug where values don't get updated...
      YAHOO.util.Dom.get("search-distance-input").value = d;
      YAHOO.util.Dom.get("search-location-input").value = l;

      YAHOO.util.Dom.get("search-submit").type = "hidden";

      // Update Link Text
      sd.innerHTML = '<a href="/page/event/search_simple" id="search-distance">' + YAHOO.util.Dom.get("search-distance-input").value + '</a>';
      if(YAHOO.util.Dom.get("search-location-input").value != YAHOO.util.Dom.get("search-location-input").defaultValue) {
        sl.innerHTML = '<a href="/page/event/search_simple" id="search-location">' + YAHOO.util.Dom.get("search-location-input").value + '</a>';
      }
    }
  },

  submitSearch: function(e) {
    BSD.event.srp.locationbar._toggleBar();
    BSD.event.srp.ajax.makeRequest({ search_radius: YAHOO.util.Dom.get('search-distance-input').value,
                                     zip: YAHOO.util.Dom.get('search-location-input').value
                                   });
    YAHOO.util.Event.stopEvent(e);
  }
};


/*** AJAX ***/
BSD.event.srp.ajax = {
  currentResults: null,
  currentSearch: new Object,
  newSearch: new Object,
  indicator: '<div id="indicator" style="font-size:18px;font-weight:bold;color:#444444;"><img src="/images/indicator.gif" style="vertical-align:middle;" alt="" /> Loading New Events...</div>',
  response: null,
  url: "/page/event/search_results?type=simple&format=json&wrap=no",

  callbackSuccess: function(o) {
    if(o.responseText !== undefined) {
      BSD.event.srp.ajax.response = YAHOO.lang.JSON.parse(o.responseText);
      var r = BSD.event.srp.ajax.response;

      BSD.event.srp.ajax._updateAnchor();

      // Update currentSearch Settings
      BSD.event.srp.ajax.currentSearch = BSD.event.srp.ajax.newSearch;

      // Update Syndication
      YAHOO.util.Dom.get('search_results_xml_link').innerHTML = '<a href="' + r.settings.gmap + '"><img alt="KML" title="KML feed for this event" class="rssimg" src="/images/kml.gif"/></a><a href="' + r.settings.rss + '"><img alt="XML" title="RSS feed for this event" class="rssimg" src="/images/xml.gif"/></a><a href="' + r.settings.ical + '"><img alt="iCal" title="iCal file for this event" class="rssimg" src="/images/ical.gif"/></a>';

      // Update Map Overlay
      if(typeof(event_map)!="undefined" && event_map.html_map){
          event_map.rss_url = r.settings.georss;
          event_map.html_map();
      } else{
          map.removeOverlay(geoxml);
          geoxml = new GGeoXml(r.settings.gmap);
          GEvent.addListener(geoxml, 'load', function() {
            geoxml.gotoDefaultViewport(map);
          });
          map.addOverlay(geoxml);
      }
      // Update Location
      if(YAHOO.util.Dom.get('search-location')) {
        YAHOO.util.Dom.get('search-location').innerHTML = r.settings.location;
      }

      // Update Count
      YAHOO.util.Dom.get('count').innerHTML = '<b>' + r.settings.count + '</b> events';

      // Update Events List
      if(r.results.length == 0) {
        YAHOO.util.Dom.get('event_list').innerHTML = '<p style="font-size:13px">Sorry, we were unable to find any events with your constraints.<br /><br />Perhaps you can try again with either a larger radius or with a greater date range?</p>';
        // TODO: suggest w/ less date constraints or bigger radius.
        return;
      } 

      el = YAHOO.util.Dom.get('event_list');

      // Date Order
      if(r.settings.orderby == 'day') {
        YAHOO.util.Dom.get('order-by-date').className = 'active';
        if(YAHOO.util.Dom.get('order-by-distance')) {
          YAHOO.util.Dom.get('order-by-distance').className = '';
        }

        el.innerHTML = '';

        var currentday = '';
        var currentmarkup = '';
        for(var i=0; i<r.results.length; i++) {
          var e = r.results[i];

          if(currentday != e.start_day) {
            currentday = e.start_day;

            // Close Table if not the first...
            if(currentmarkup) { currentmarkup += '</tbody></table>'; }

            // Flush Table
            if(currentmarkup) {
              el.innerHTML += currentmarkup;
              currentmarkup = '';
            }

            var datebox = '<div class="datebox"><div class="english">' + BSD.event.srp.util.englishDay(e.start_day) + '</div><div class="calendardate"><span class="month">' + BSD.event.srp.util.shortMonth(e.start_day) + '</span><br /><span class="day">' + e.start_day.split('-')[2] + '</span></div></div>';
            currentmarkup += '<table class="event_group"><tbody><tr class="first"><th valign="top">' + datebox + '</th>';
          } else {
            currentmarkup += '<tr><td>&nbsp;</td>';
          }

          dateclass = e.shifttimes ? 'date shift' : 'date';
          eventtime = e.shifttimes ? 'Shifts begin at ' + e.shifttimes + ' (' + e.shiftcount + ' shifts)': BSD.event.srp.util.englishTime(e.start_time);

          // Event
          currentmarkup += '<td class="event"><h3 class="title"><a href="' + e.url + '">' + e.name + '</a></h3><div class="' + dateclass + '"><span class="day">' + BSD.event.srp.util.englishDate(e.start_day) + '</span> <span class="time">' + eventtime + '</span></div><div class="location"><span class="venue">' + e.venue_name + '</span> <span class="city">(' + e.venue_city + ', ' + e.venue_state_cd + ')</span></div><div class="description">' + e.description + '</div><div class="event_footer"><div class="event_type"><small>' + e.event_type_name + '</small></div><div class="links"><div class="rsvp_button"><a href="' + e.url + '#rsvp">RSVP &raquo;</a></div><div class="detail_button"><a href="' + e.url + '">Details &raquo;</a></div></div></div></td></tr>';
        }

        // Final Flush
        currentmarkup += '</tbody></table>';
        el.innerHTML += currentmarkup;

      // Distance Order
      } else {
        YAHOO.util.Dom.get('order-by-date').className = '';
        YAHOO.util.Dom.get('order-by-distance').className = 'active';

        el.innerHTML = '';

        var distance = 0;
        var currentmarkup = '';
        for(var i=0; i<r.results.length; i++) {
          var e = r.results[i];

          if(e.distance > distance) {
            if(e.distance <= 1) {
              distance = 1;
            } else if(e.distance <= 2) {
              distance = 2;
            } else if(e.distance <= 5) {
              distance = 5;
            } else if(e.distance <= 10) {
              distance = 10;
            } else if(e.distance <= 20) {
              distance = 20;
            } else if(e.distance <= 30) {
              distance = 30;
            } else if(e.distance <= 50) {
              distance = 50;
            } else {
              distance += 25;
            }

            // Close Table if not the first...
            if(currentmarkup) { currentmarkup += '</tbody></table>'; }

            // Flush Table
            if(currentmarkup) {
              el.innerHTML += currentmarkup;
              currentmarkup = '';
            }

            var datebox = '<div class="datebox"><div class="english">&lt; ' + distance + '.0 ' + r.settings.radius_unit + '</div></div>';
            currentmarkup += '<table class="event_group"><tbody><tr class="first"><th valign="top">' + datebox + '</th>';
          } else {
            currentmarkup += '<tr><td>&nbsp;</td>';
          }

          dateclass = e.shifttimes ? 'date shift' : 'date';
          eventtime = e.shifttimes ? 'Shifts begin at ' + e.shifttimes + ' (' + e.shiftcount + ' shifts)': BSD.event.srp.util.englishTime(e.start_time);

          // Event
          currentmarkup += '<td class="event"><h3 class="title"><a href="' + e.url + '">' + e.name + '</a></h3><div class="' + dateclass + '"><span class="day-show">' + BSD.event.srp.util.englishDate(e.start_day) + '</span> <span class="time">' + eventtime + '</span></div><div class="location"><span class="venue">' + e.venue_name + '</span> <span class="city">(' + e.venue_city + ', ' + e.venue_state_cd + ')</span></div><div class="description">' + e.description + '</div><div class="event_footer"><div class="event_type"><small>' + e.event_type_name + '</small></div><div class="links"><div class="rsvp_button"><a href="' + e.url + '#rsvp">RSVP &raquo;</a></div><div class="detail_button"><a href="' + e.url + '">Details &raquo;</a></div></div></div></td></tr>';
        }

        // Final Flush
        currentmarkup += '</tbody></table>';
        el.innerHTML += currentmarkup;

      }

      // BSD.event.srp.ajax._toggleIndicator('off');
    }
  },

  callbackFailure: function(o) {
    BSD.event.srp.ajax._toggleIndicator('off');

    alert("Sorry, we couldn't contact the server.  Please try again or try reloading the page.  If this error persists, please let us know!");
  },

  makeRequest: function(newSearch) {
    var callback = {
      success: BSD.event.srp.ajax.callbackSuccess,
      failure: BSD.event.srp.ajax.callbackFailure,
      scope: BSD.event.srp.ajax
    };

    // Check to see if we should AJAX
    // No new search? Stop.
    if(!newSearch) { return false; }
    var different = 0;
    for(var attr in newSearch) { 
      if(newSearch[attr] != BSD.event.srp.ajax.currentSearch[attr]) {
        different++;
      }
    }
    // No changes? Stop.
    if(!different) { return false; }

    // Create New Search
    for(var attr in BSD.event.srp.ajax.currentSearch) {
      if(!newSearch[attr]) {
        newSearch[attr] = BSD.event.srp.ajax.currentSearch[attr];
      }
    }

    // Remove -1
    for(var attr in newSearch) {
      if(newSearch[attr] == -1) {
        delete newSearch[attr];
      }
    }

    BSD.event.srp.ajax.newSearch = newSearch;

    // Make Request
    var url = BSD.event.srp.ajax.url;
    for(var newattr in newSearch) {
      if(newattr == 'zip') {
        url += "&zip_radius[0]=" + newSearch[newattr];
      } else if(newattr == 'search_radius') {
        url += "&zip_radius[1]=" + newSearch[newattr];
      } else if(YAHOO.lang.isArray(newSearch[newattr])) {
        for(var i=0; i<newSearch[newattr].length; i++) {
          url += "&" + newattr + "[]=" + newSearch[newattr][i];
        }
      } else if(newattr != 'location' && newattr != 'rss' && newattr != 'ical') {
        url += "&" + newattr + "=" + newSearch[newattr];
      }
    }
    /*
    (newSearch.orderby) ? url += "&orderby=" + newSearch.orderby : false;
    (newSearch.zip) ? url += "&zip_radius[0]=" + newSearch.zip : false;
    (newSearch.search_radius) ? url += "&zip_radius[1]=" + newSearch.search_radius : false;
    (newSearch.radius_unit) ? url += "&radius_unit=" + newSearch.radius_unit : false;
    (newSearch.country) ? url += "&country=" + newSearch.country : false;
    (newSearch.date_start) ? url += "&date_start=" + newSearch.date_start : false;
    (newSearch.date_end) ? url += "&date_end=" + newSearch.date_end : false;
    (newSearch.event_type) ? url += "&event_type=" + newSearch.event_type : false;
    (newSearch.state) ? url += "&state=" + newSearch.state : false;
    (newSearch.limit) ? url += "&limit=" + newSearch.limit : false;
    */

    var request = YAHOO.util.Connect.asyncRequest('GET', url, callback);
    BSD.event.srp.ajax._toggleIndicator('on');
  },

  makeRequestFromAnchor: function() {
    // TODO: _parseAnchor into newSearch and update
  },

  _parseAnchor: function() {
  },

  _toggleIndicator: function(toggle) {
    // Not the most efficient...
    if(toggle == 'off' || !toggle) {
      if(BSD.event.srp.ajax.currentResults) {
        YAHOO.util.Dom.get('event_list').innerHTML = BSD.event.srp.ajax.currentResults;
      }
    } else {
      if(YAHOO.util.Dom.get('event_list').innerHTML.indexOf('<div id="indicator"') == -1) {
        BSD.event.srp.ajax.currentResults = YAHOO.util.Dom.get('event_list').innerHTML;
        YAHOO.util.Dom.get('event_list').innerHTML = BSD.event.srp.ajax.indicator;
      }
    }
  },

  _updateAnchor: function() {
    // TODO: Generate Anchor from currentSearch properties
  }

};

/*** Event SRP Utils ***/
BSD.event.srp.util = {
  mon: ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'], 
  months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], 
  days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],

  englishDay: function(myd) {
    myd = myd.split('-');
    var d = new Date();
    if(myd[0] == d.getFullYear() && myd[1] == (d.getMonth()+1) && myd[2] == d.getDate()) {
      return 'Today';
    }
    d = new Date(d.getTime() + 86400000);
    if(myd[0] == d.getFullYear() && myd[1] == (d.getMonth()+1) && myd[2] == d.getDate()) {
      return 'Tomorrow';
    }

    d = new Date(myd[0], myd[1]-1, myd[2]);
    return BSD.event.srp.util.days[d.getDay()];
  },

  englishDate: function(myd) {
    myd = myd.split('-');
    d = new Date(myd[0], myd[1]-1, myd[2]);
    return BSD.event.srp.util.days[d.getDay()] + ', ' + BSD.event.srp.util.months[(myd[1]-1)] + ' ' + d.getDate();
  },

  englishTime: function(t) {
    t = t.split(':');
    if(t[0] == '00') {
      return '12:' + t[1] + ' AM';
    } else if(t[0] < '12') {
      return t[0] + ':' + t[1] + ' AM';
    } else if(t[0] == '12') {
      return '12:' + t[1] + ' PM';
    } else {
      return (t[0]-12) + ':' + t[1] + ' PM';
    }

  },

  shortMonth: function(myd) {
    return BSD.event.srp.util.mon[myd.split('-')[1]-1];
  }
};

/*** Interval Calendar ***/
(function() {
    /**
    * IntervalCalendar is an extension of the CalendarGroup designed specifically
    * for the selection of an interval of dates.
    *
    * @namespace BSD.event.srp.calendar
    * @module calendar
    * @since 2.5.2
    * @requires yahoo, dom, event, calendar
    *
    * See: http://developer.yahoo.com/yui/examples/calendar/intervalcal.html
    */
    function IntervalCalendar(container, cfg) {
        this._iState = 0;

        // Must be a multi-select CalendarGroup
        cfg = cfg || {};
        cfg.multi_select = true;

        // Call parent constructor
        IntervalCalendar.superclass.constructor.call(this, container, cfg);

        // Subscribe internal event handlers
        this.beforeSelectEvent.subscribe(this._intervalOnBeforeSelect, this, true);
        this.selectEvent.subscribe(this._intervalOnSelect, this, true);
        this.beforeDeselectEvent.subscribe(this._intervalOnBeforeDeselect, this, true);
        this.deselectEvent.subscribe(this._intervalOnDeselect, this, true);
    }

    IntervalCalendar._DEFAULT_CONFIG = YAHOO.widget.CalendarGroup._DEFAULT_CONFIG;

    YAHOO.lang.extend(IntervalCalendar, YAHOO.widget.CalendarGroup, {
        _dateString : function(d) {
            var a = [];
            a[this.cfg.getProperty(IntervalCalendar._DEFAULT_CONFIG.MDY_MONTH_POSITION.key)-1] = (d.getMonth() + 1);
            a[this.cfg.getProperty(IntervalCalendar._DEFAULT_CONFIG.MDY_DAY_POSITION.key)-1] = d.getDate();
            a[this.cfg.getProperty(IntervalCalendar._DEFAULT_CONFIG.MDY_YEAR_POSITION.key)-1] = d.getFullYear();
            var s = this.cfg.getProperty(IntervalCalendar._DEFAULT_CONFIG.DATE_FIELD_DELIMITER.key);
            return a.join(s);
        },

        _dateIntervalString : function(l, u) {
            var s = this.cfg.getProperty(IntervalCalendar._DEFAULT_CONFIG.DATE_RANGE_DELIMITER.key);
            return (this._dateString(l)
                    + s + this._dateString(u));
        },

        getInterval : function() {
            // Get selected dates
            var dates = this.getSelectedDates();
            if(dates.length > 0) {
                // Return lower and upper date in array
                var l = dates[0];
                var u = dates[dates.length - 1];
                return [l, u];
            }
            else {
                // No dates selected, return empty array
                return [];
            }
        },

        setInterval : function(d1, d2) {
            // Determine lower and upper dates
            var b = (d1 <= d2);
            var l = b ? d1 : d2;
            var u = b ? d2 : d1;
            // Update configuration
            this.cfg.setProperty('selected', this._dateIntervalString(l, u), false);
            this._iState = 2;
        },

        resetInterval : function() {
            // Update configuration
            this.cfg.setProperty('selected', [], false);
            this._iState = 0;
        },

        _intervalOnBeforeSelect : function(t,a,o) {
            // Update interval state
            this._iState = (this._iState + 1) % 3;
            if(this._iState == 0) {
                // If starting over with upcoming selection, first deselect all
                this.deselectAll();
                this._iState++;
            }
        },

        _intervalOnSelect : function(t,a,o) {
            // Get selected dates
            var dates = this.getSelectedDates();
            if(dates.length > 1) {
                var l = dates[0];
                var u = dates[dates.length - 1];
                this.cfg.setProperty('selected', this._dateIntervalString(l, u), false);
            }
            // Render changes
            this.render();
        },

        _intervalOnBeforeDeselect : function(t,a,o) {
            if(this._iState != 0) {
                return false;
            }
        },

        _intervalOnDeselect : function(t,a,o) {
            if(this._iState != 0) {
                // If part of an interval is already selected, then first deselect all
                this._iState = 0;
                this.deselectAll();

                // Get individual date deselected and page containing it
                var d = a[0];
                var date = YAHOO.widget.DateMath.getDate(d[0], d[1] - 1, d[2]);
                var page = this.getCalendarPage(date);
                if(page) {
                    // Now (re)select the individual date
                    page.beforeSelectEvent.fire();
                    this.cfg.setProperty('selected', this._dateString(date), false);
                    page.selectEvent.fire([d]);
                }
                // Swallow up since we called deselectAll above
                return false;
            }
        }
    });

    BSD.namespace("event.srp.calendar");
    BSD.event.srp.calendar.IntervalCalendar = IntervalCalendar;
})();


/*** Giddy On Up Cowboy ***/
YAHOO.util.Event.onDOMReady(function() {
  // We have JS
  if(!YAHOO.env.ua.ie || YAHOO.env.ua.ie >= 7) {
    YAHOO.util.Dom.get('calendar-nav').style.display = 'block';
  }
  if(YAHOO.env.ua.ie >= 7) {
    // IE7 Branch for Calendar
    YAHOO.util.Dom.get('filters').style.width = '180px';
    YAHOO.util.Event.addListener("date-filter", "click", function(e) {
      var s = YAHOO.util.Dom.get("date-start").value.split('/');
      var e = YAHOO.util.Dom.get("date-end").value.split('/');
      if(e.length == 1) { e = s; }

      if(s.length > 1 && e.length > 1) {
        window.location = window.location.toString().replace(/&date_(start|end)=\d*/g, '') + '&date_start=' + (new Date(s[2], s[0]-1, s[1]).getTime()/1000) + '&date_end=' + (new Date(e[2], e[0]-1, e[1]).getTime()/1000 + 86399);
      }
      YAHOO.util.Event.stopEvent(e);
    });
  }

  // Preload IMG
  img = new Image();
  img.src = '/skins/obama/event2/datebg.png';

  // Location Bar
  if(!YAHOO.env.ua.ie) {
    YAHOO.util.Event.addListener("search-distance", "click", BSD.event.srp.locationbar.editSearchDistance);
    YAHOO.util.Event.addListener("search-location", "click", BSD.event.srp.locationbar.editSearchLocation);
    YAHOO.util.Event.addListener("search-submit", "click", BSD.event.srp.locationbar.submitSearch);
  }

  // Interval Calendar
  var inTxt = YAHOO.util.Dom.get("date-start"),
      outTxt = YAHOO.util.Dom.get("date-end"),
      inDate, outDate, interval;

  if(inTxt.value) {
    var d = new Date(inTxt.value*1000);
    inTxt.value = (d.getMonth()+1) + "/" + d.getDate() + "/" + d.getFullYear();
  }
  if(outTxt.value) {
    var d = new Date(outTxt.value*1000);
    outTxt.value = (d.getMonth()+1) + "/" + d.getDate() + "/" + d.getFullYear();
  }

  var cal = new BSD.event.srp.calendar.IntervalCalendar("calendar", {pages:1, mindate:new Date()});

  cal.selectEvent.subscribe(function() {
    interval = this.getInterval();

    if (interval.length == 2) {
      inDate = interval[0];
      inTxt.value = (inDate.getMonth() + 1) + "/" + inDate.getDate() + "/" + inDate.getFullYear();

      if (interval[0].getTime() != interval[1].getTime()) {
        outDate = interval[1];
        outTxt.value = (outDate.getMonth() + 1) + "/" + outDate.getDate() + "/" + outDate.getFullYear();
      } else {
        outTxt.value = "";
      }
    }
  }, cal, true);

  cal.render();

  // Parse Anchor
  BSD.event.srp.ajax.makeRequestFromAnchor();

  // Order By
  if(!YAHOO.env.ua.ie) {
    YAHOO.util.Event.addListener("order-by-date-link", "click", function(e) {
      BSD.event.srp.ajax.makeRequest({ orderby: 'day'});
      YAHOO.util.Event.stopEvent(e);
    });
    YAHOO.util.Event.addListener("order-by-distance-link", "click", function(e) {
      BSD.event.srp.ajax.makeRequest({ orderby: 'zip_radius'});
      YAHOO.util.Event.stopEvent(e);
    });

    // Filter Dates
    YAHOO.util.Event.addListener("date-filter", "click", function(e) {
      var s = YAHOO.util.Dom.get("date-start").value.split('/');
      var e = YAHOO.util.Dom.get("date-end").value.split('/');

      // Single Day
      if(e.length == 1) {
        e = s;
      }

      if(s.length > 1 && e.length > 1) {
        BSD.event.srp.ajax.makeRequest({ date_start: new Date(s[2], s[0]-1, s[1]).getTime()/1000,
                                         date_end: new Date(e[2], e[0]-1, e[1]).getTime()/1000 + 86399
                                       });
      } else {
        // -1 to remove values - hacky yes, but less confusing than using === and !===
        BSD.event.srp.ajax.makeRequest({date_start: -1, date_end: -1});
      }
      YAHOO.util.Event.stopEvent(e);
    });
  }

  // Original Search
  BSD.event.srp.ajax.currentSearch = currentSearch;
});
