
// constructor for CampusEvent object
//  has 
//      a Place object
//      start and end times
//      feed item (from Google Feed API )
function CampusEvent( where , whenStart, whenEnd, rss, what )
{
    // events can have multiple places
    // so let's create an array
    this.places = [];
    // and then initialize the first in the array to the place passed in
    // can add more later with the addPlace method 
    this.places.push( where );
    this.startDate = whenStart;
    this.endDate   = whenEnd;
    this.feedItem  = rss ;
//     alert(" rss = " + rss );
//     var titleElement = google.feeds.getElementsByTagNameNS( rss , "http://www.w3.org/2005/Atom", "title")[0];
//     this.headline = titleElement.firstChild.nodeValue;
    this.headline = what;
}

function CampusEvent( rssEntry )
{
    var titleElement = google.feeds.getElementsByTagNameNS(rssEntry, "http://www.w3.org/2005/Atom", "title")[0];
//     var title = titleElement.firstChild.nodeValue;
//     this.headline = title;
    this.headline = titleElement.firstChild.nodeValue;

    var descElement =  google.feeds.getElementsByTagNameNS(rssEntry, "http://www.w3.org/2005/Atom", "content")[0];
    this.description = descElement.firstChild.nodeValue;

    var mylinkElement = google.feeds.getElementsByTagNameNS(rssEntry, "http://www.w3.org/2005/Atom", "link")[0];
    var mylink = mylinkElement.getAttribute('href');

    // change the link for adding the calendar to make it so that it adds to the user's ASU domain calendar
//     var newlink = mylink.replace("calendar/event", "calendar/hosted/asu.edu/event");

    var whenElement = google.feeds.getElementsByTagNameNS(rssEntry, "http://schemas.google.com/g/2005", "when")[0];
    var starttime = whenElement.getAttribute('startTime');
    var endtime = whenElement.getAttribute('endTime');

//     var startDate = new Date();
    this.startDate = new Date();
    this.startDate.setISO8601(starttime, "-0700" );
//     this.startDate = startdate;

//     var enddate = new Date();
    this.endDate = new Date();
    this.endDate.setISO8601(endtime, "-0700" );
//     this.endDate = enddate;
    
    var whereElement = google.feeds.getElementsByTagNameNS(rssEntry, "http://schemas.google.com/g/2005", "where")[0];
    var whereString = whereElement.getAttribute('valueString');
    this.whereString = whereString;

    this.places = [];

    this.places = parseForPlaceNames( whereString )

//     var startstring = (startdate.getMonth() + 1) + '/' + (startdate.getDate() + 1) + '/' + startdate.getFullYear();
//     var endstring = (enddate.getMonth() + 1) + '/' + (enddate.getDate() + 1) + '/' + enddate.getFullYear();
//
//     if (startstring == endstring) 
//     {
//       whenstring = '(' + startstring + ')';
//     }
//     else 
//     {
//       whenstring = '(' + 'starting: ' + startstring + ' ' + 'ending: ' + endstring + ')';
//     }
    
    this.feedItem = rssEntry;
}

// takes a string
// returns array of place codes (3-letter building codes)
function parseForPlaceNames( locationString )
{
    var matchedPlaces = [];
    var debug = ("ACES Avaya Auditorium (ACE 2.302)" == locationString);

    // first search for plain building codes as a 3-letter chunk by themselves (checks word boundaries)
    for (var i=0; i< allPlaces.length; i++)
    {
        var bldgCode = allPlaces[i].code ;
        if (bldgCode && bldgCode != "" && bldgCode != "   " ) 
        {
            var regex = new RegExp( "\\b" + bldgCode + "\\b"  , "" );
            var results = regex.exec( locationString );
            if ( results != null )
            {
                matchedPlaces.push( allPlaces[i] );
                break;
            }
        }
    }

    // next search for building name strings
    for (var i=0; i< allPlaces.length; i++)
    {
        var bldgstring = allPlaces[i].name ;
        if (bldgstring != "" ) 
        {
            var regex = new RegExp( "\\b" + bldgstring + "\\b"  , "i" );
            var results = regex.exec( locationString );
            if ( results != null )
            {
                matchedPlaces.push( allPlaces[i] );
                break;
            }
        }
    }

    // now search our building alias list
    for (var i=0; i<buildingAliases.length; i++)
    {
        var bldgCode = buildingAliases[i].code;
        var aliasArray = buildingAliases[i].aliases;
        for (aliasIndex=0; aliasIndex < aliasArray.length; aliasIndex++)
        {
            var regex = new RegExp( "\\b" + aliasArray[ aliasIndex ] + "\\b", "i" );
            var results = regex.exec( locationString )
            if (results != null)
            {
                matchedPlaces.push( new CampusPlace( {code:bldgCode} ) );
                break;
            } 
        }
    }

    return matchedPlaces;
}

CampusEvent.prototype.addPlace = function( where  )
{
//     this.places[ this.places.length ] = where;
    this.places.push( where );
}

CampusEvent.prototype.toString = function()
{
    var string = "Event: " + this.headline
//     string += "More: " + this.description;
//     string += "<br/>Starts: " + this.startDate;
//     string += "<br/>Ends: "   + this.endDate;
//     string += "<br/>Place: " + this.whereString + " --> " 
//     string += "(" + this.places.length + " places total)";
    if (this.places.length > 0 ) { 
        string += this.places[0].code.toUpperCase() ;
    }
    return string;
}


// CampusEvent method: addMeToTimeline( evtSrc )
//  input : EventSource object to which this event should be added
//  output : none
//  action : (this) event is added to the specified EventSource (and in turn the appropriate timeline)
CampusEvent.prototype.addMeToTimeline = function ( evtSrc )
{
    // create a new Timeline Event object, populated with data from the CampusEvent object
    var evt = new Timeline.DefaultEventSource.Event(
        this.startDate, 
        this.endDate,
        this.startDate, 
        this.endDate,
        null, // latest_start_date, - only for fuzzy events, not used here
        null, // earliest_end_date, - only for fuzzy events, not used here
        (this.startDate == this.endDate), // is this an instant event?
        this.headline ,     // the title of the event, will show up on the timeline and as the header of the popup info window
        this.description,   // body text used for the info window
        null, null, null,   // image, link, icon,
        null, null          // color, textColor
    );
//             evt._node = node;
//             evt.getProperty = function(name) {
//                 return this._node.getAttribute(name);
//             };
//             evt.setWikiInfo(wikiURL, wikiSection);
            
//             this._events.add(evt);
//             this._fire("onAddMany", []);
    evtSrc._events.add( evt );
}

CampusEvent.prototype.toTimelineEvent = function( eventListIndex )
{
    var linkifiedDescription = 
              ((this.places.length >0) ? (
                    "<a href=\"javascript:highlightEventOnMap(" 
                +  eventListIndex 
                + "); selectEventInList(" 
                +  eventListIndex 
                + ");\">" 
                + "(show on map - "  
                + this.places[0].code.toUpperCase()
                + ")</a><br/>" 
              ) : "" ) 
              + this.description;
    return new Timeline.DefaultEventSource.Event(
                this.startDate, 
                this.endDate,
//                 this.startDate, 
//                 this.endDate,
                null, // latest_start_date, 
                null, // earliest_end_date,
                (this.startDate == this.endDate), // && latest_start_date == earliest_end_date),
                this.headline ,
                linkifiedDescription,
                null, null, null, // image, link, icon,
                "#c50", "#000" // color, textColor
            );
}

function selectEventInList( indexOfEvent )
{

    if ( selectedEventIndex >= 0)
    {
        if (selectedEventIndex == indexOfEvent)
        {
            //$("#eventDescription" + selectedEventIndex ).hide("slow");
        }
        else
        {
            $("#eventItem" + selectedEventIndex).removeClass("selectedEventItem");
            $("#eventDescription" + selectedEventIndex ).hide("slow");
        }
    }


        $("#eventDescription" + indexOfEvent ).show("slow");
    if (selectedEventIndex != indexOfEvent)
    {
        window.location.href = "#eventItem" + indexOfEvent ;
        $("#eventItem" + indexOfEvent).addClass("selectedEventItem");
        window.location.href = "#eventItem" + indexOfEvent ;
        highlightEventOnMap( indexOfEvent );
    }
    recenterTimeline( indexOfEvent );

    selectedEventIndex = indexOfEvent;

//     return "#eventItem" + selectedEventIndex;
}

CampusEvent.prototype.toListElement = function( eventListIndex )
{
    //var rc_element = $("<p></p>");
    var rc_element = document.createElement("p");
    $(rc_element).addClass("eventItem");
    $(rc_element).attr("id", "eventItem" + eventListIndex );
    $(rc_element).bind("click", function()  { selectEventInList( eventListIndex )});

    if ( this.startDate.toDateString() == this.endDate.toDateString() ) 
    {
        $(rc_element).append( 
                        $('<span class="eventDate"></span>')
                        .text( dateFormat( this.startDate, "fullDate") ) ); 
//         $(rc_element).append( "<br/>" );
        $(rc_element).append( " - " );
        $(rc_element).append( 
                        $('<span class="eventTime"></span>').
                        text(  dateFormat( this.startDate, "h:MM tt" )
                               + " - " + 
                               dateFormat( this.endDate, "h:MM tt"  )
                          )
                        );
         //$(rc_element).append( $("<br/>") );
    } 
    else 
    {
        $(rc_element).append( $('<span class="eventDate"></span>' )
                              .text( "Starting " + dateFormat( this.startDate , "fullDate" ) )
                            ); 
        $(rc_element).append("<br/>");
        $(rc_element).append( $('<span class="eventTime">' )
                              .text( "until " + dateFormat( this.endDate, "fullDate" ) )
                            );
    }

    $(rc_element).append( $("<br/>") );
    $(rc_element).append( $('<span class="eventTitle"></span>').text( this.headline ) );
    this.description = this.description.replace( /url=([^ ]*) ([^\/]*)\/url/g , '<a href="$1">$2</a>');
    $(rc_element).append( 
                    $('<div id="eventDescription' + eventListIndex + '" style="display: none;"></div>' )
                    .append($("<a href='#'></a>")
                            .text("(Hide full description)") 
                            .bind(
                                "click",
                                function() { 
                                    $('#eventDescription' + eventListIndex ).hide('slow'); return false; 
                                }
                            )
                    )
                    .append($("<p>" + this.description + "</p>") )
                );
    $(rc_element).append( $("<br/>") );
    //$(rc_element).append( 
            //this.whereString + ( this.places[0] ? " (" + this.places[0].code.toUpperCase() + ") " : ""   ) 
            //);

    if ( this.places.length > 0)
    {
        $(rc_element).append( $(
                    linkToMapByIndex( 
                        eventListIndex  ,  
                        this.whereString + ( this.places[0] ? " (" + this.places[0].code.toUpperCase() + ") " : ""   ) 
                    )
                ) );
    } else {
        $(rc_element).append( this.whereString  );
    }
    return rc_element;
}

function clearEventList( )
{
    CampusEventList = [];
    var eldiv = document.getElementById("events"); 
    for (var i=0; i<eldiv.childNodes.length; i++)
        $(eldiv.childNodes[i]).fadeOut("slow");
}

function refreshTimeline( eventListToDisplay )
{
//                 eventSource = new Timeline.DefaultEventSource(0); 
            eventSource.clear();
            for (var i=0; i< eventListToDisplay.length; i++)
            {
                if (eventListToDisplay[i].show )
                {
                    // add each event to the timeline
                    eventSource.add( eventListToDisplay[i].toTimelineEvent( i ) );
                }
            }
            eventSource._fire("onAddMany",[]);
//             softAlert( eventListToDisplay.length + " events loaded from feed");
}


function refreshEventList( eventListToDisplay )
{
    var eldiv = document.getElementById("events"); 
    var daterangeEnd, daterangeStart;
    while (eldiv.firstChild)
    {
        eldiv.removeChild( eldiv.firstChild );
    }

    if ($("#startpicker").val() == "") 
    {
        var daterangeStart = eventListToDisplay[0].startDate;
        $("#startpicker").datepicker("setDate", daterangeStart );
        $("#startpicker").datepicker().val( dateFormat( daterangeStart, "mm/dd/yyyy") );
    } else {
        var daterangeStart = $("#startpicker").datepicker("getDate");
    }
    daterangeStart = new Date( daterangeStart.toDateString() ) ;

    if ($("#endpicker").val() == "" )
    {
        var daterangeEnd = eventListToDisplay[ eventListToDisplay.length - 1 ].startDate;
        $("#endpicker").datepicker("setDate", daterangeEnd );
        $("#endpicker").datepicker().val( dateFormat( daterangeEnd , "mm/dd/yyyy") );
    }
    else
    {
        var daterangeEnd = $("#endpicker").datepicker("getDate");
    }
    daterangeEnd = new Date( daterangeEnd.toDateString() ) ;
    daterangeEnd.setDate( daterangeEnd.getDate() + 1 );

//     $("#onepicker").datepicker("setDate", eventListToDisplay[0].startDate.toDateString() , eventListToDisplay[ eventListToDisplay.length -1 ].startDate.toDateString() );
// alert("setDate from "+ eventListToDisplay[0].startDate + " to " +  eventListToDisplay[ eventListToDisplay.length -1 ].startDate );

    for (var i=0; i< eventListToDisplay.length; i++)
    {
        var foundAtLeastOne = false;
        // add each event to the list in the sidebar
        if (   ( daterangeStart <= eventListToDisplay[i].startDate )
            && ( eventListToDisplay[i].startDate <= daterangeEnd ) 
           )
        {
            var eventElement = eventListToDisplay[ i ].toListElement( i );
            eldiv.appendChild( eventElement );
            foundAtLeastOne = true;
            eventListToDisplay[i].show = true;
        }
        else 
        {
            eventListToDisplay[i].show = false;
//             alert("Discarding '" + eventListToDisplay[i].headline + "' (not in range from " + daterangeStart + " to " + daterangeEnd + " ) " ) ;
        }
    }
    refreshTimeline( eventListToDisplay );
}

function linkToMapByIndex( index, text )
{
    var linkToMap = document.createElement("a");
    $(linkToMap).attr("href", "javascript:highlightEventOnMap(" + index + ");" );
    $(linkToMap).text( text );
    return linkToMap;

}

function highlightEventOnMap( index )
{
    if ( index < CampusEventList.length )
    {
        var currentEvent = CampusEventList[ index ];
        if ( currentEvent.places.length > 0)
        {
            var knownLocation = false;
            for (var i=0; i<currentEvent.places.length; i++)
            {
                knownLocation = knownLocation || currentEvent.places[i].isLocationKnown();
                var popupText = '<h3><a href="javascript:selectEventInList(' + index + ')">' + currentEvent.headline + '</a></h3>';
                    popupText += currentEvent.description ? ("<br/>" + currentEvent.description ): "";
                currentEvent.places[i].addMeToGMap(map, popupText, currentEvent.places[i].type );
            }
            if ( knownLocation ) 
            {
                currentEvent.places[0].centerOnMe();
                // make the info window popup *now*
                GEvent.trigger( currentEvent.places[0].marker, "click" );
            } 
            else
            { 
                softAlert("Sorry, I don't know the location of " + currentEvent.places[0].name + " (" + currentEvent.places[0].code + ")" );
            }
        }
    } 
    else
    {
        // TODO index out of range .. do something
    }
    //     return false;
}

function recenterTimeline( index )
{
    var newCenterDate = CampusEventList[ index ].startDate;
    tl._bands[0].setCenterVisibleDate( newCenterDate );

}


function sortEventByDateRev( a, b )
{
    return ( 
            ( b.startDate>a.startDate )
            - 
            ( a.startDate>b.startDate ) 
        );
}

function sortEventByDate( a, b )
{
    return ( 
            ( a.startDate>b.startDate ) 
            - 
            ( b.startDate>a.startDate )
        );
}

function clearAndLoadFeed( eventFeed )
{
    clearEventList();
    loadFeed( eventFeed );
}

function loadAllFeeds()
{
    clearEventList();
    for (var name in eventFeeds )
    {
        loadFeed( eventFeeds[ name ] );
    }
}

function loadFeed( eventFeed )
{
    $(".datefield").val("");
    var feed = new google.feeds.Feed( eventFeed.URL );
    feed.setResultFormat( google.feeds.Feed.XML_FORMAT );

    // Default value displays only four feed entries
    feed.setNumEntries( maxFeedItems );
    feed.load(
        function(result) {
            var eldiv = document.getElementById("events"); 
            if (!result.error) 
            {
                var entries = google.feeds.getElementsByTagNameNS(result.xmlDocument, "http://www.w3.org/2005/Atom", "entry");
                for (var i = 0; i < entries.length; i++) 
                {
                    CampusEventList.push( new CampusEvent( entries[i] ) );
                }
            }
            else
            { 
//                 var errorText;
//                 var failCount = 0;
                if ( failCount < maxFails )
                {
                  errorText = document.createTextNode( 
                      " There was a problem loading the calendar feed.  Sit tight, I'll try again shortly.  " 
                      + "(status " + result.error.code + ", message was '" + result.error.message + "') " 
                    );
                  setTimeout(  "initEventFeed()", errorRetryInterval * failCount );
                }
                else
                {
                  errorText = document.createTextNode( 
                          "I had problems loading the calendar feed" 
                        + (
                            (failCount > 1) 
                            ? " ( tried loading " + failCount + " times )" 
                            : "" )
                        + ".   Try reloading this page.  If it keeps happening, please bug my owner about this." 
                    ); 
                    // TODO provide feedback/complaint link or email address
                }

//                 alert( "failCount = " + failCount );
//                 var errorP;
                if ( failCount == 0 )
                {
                  errorP = document.createElement("p");
                  $(errorP).attr("id", "errorMessage");
                  errorP.appendChild( errorText );
                }
                else
                {
                  errorP = document.getElementById("errorMessage");
                  if ( errorP )
                    errorP.replaceChild( errorText, errorP.firstChild );
                }
                eldiv.appendChild( errorP );
                failCount++;
            }

            CampusEventList.sort( sortEventByDate );

//                         refreshEventList( slice( CampusEventList( ) );
            $('.datefield').val("");
            filterEventsByDate();
//             refreshEventList( CampusEventList );


        }  // end of feed.load callback
    );
}

function getThisWeek( )
{
    // start with today's date
    var weekFirst =  new Date();
    // subtract the number of the day of the week (plus 1), to get Monday
    weekFirst.setDate( weekFirst.getDate() - weekFirst.getDay() + 1 );

    // then add seven to get next sunday
    var weekLast = new Date( weekFirst );
    weekLast.setDate( weekFirst.getDate() + 6 );
    return [ weekFirst, weekLast ];
}

function getThisWeekend( )
{
    // start with today's date
    var today =  new Date();
    today.setDate( today.getDate() + 3 );
    var thursday = new Date();
    var sunday = new Date();
    
    // add (4 minus today's DOW no.) to get Thursday
    thursday.setDate( today.getDate() + (4 - today.getDay() ) );
    // add (7 minus today's DOW no.) to get Thursday
    sunday.setDate( today.getDate() + (7 - today.getDay() ) );

    // then add seven to get next sunday
    return [ thursday, sunday ];
}

function getThisMonth( )
{
    var start = new Date();
    start.setDate( 1 );
    var end = new Date( start );
    end.setMonth( start.getMonth() + 1 );
    end.setDate( 0 );
    return [ start, end ];
}

function setRangeEndpoint( startendDate, startORend )
{
    $("#" + startORend + "picker").datepicker("setDate", startendDate ); 
    $("#" + startORend + "picker").val( dateFormat( startendDate, "mm/dd/yyyy" ) );
}

function filterEventsByDate()
{
    var filterType = $("#dateFilterType").val();
    if(filterType == "pickrange") 
    { 
        $("#pickers").slideDown(); 
    } else { 
        $("#pickers").slideUp();
        switch (filterType) 
        {
            case 'thismonth':
                var month = getThisMonth();
                setRangeEndpoint( month[0], "start" );
                setRangeEndpoint( month[1], "end" );
                refreshEventList(CampusEventList);
                break;
            case 'thisweek':
                var week = getThisWeek();
                setRangeEndpoint( week[0], "start" );
                setRangeEndpoint( week[1], "end" );
                refreshEventList(CampusEventList);
                break;
            case 'thisweekend':
                var weekend = getThisWeekend();
                setRangeEndpoint( weekend[0], "start" );
                setRangeEndpoint( weekend[1], "end" );
                refreshEventList(CampusEventList);
                break;
            case 'today':
                setRangeEndpoint( new Date(), "start" );
                setRangeEndpoint( new Date(), "end" );
                refreshEventList(CampusEventList);
                break;

            case 'whenever':
                $(".datefield").val("");
                refreshEventList( CampusEventList );
                break;
        }
    } 
}

