/****************************
 Parse Event Date
 *****************************/
function EventTabJSONParser(){
    this.tab;
    this.project;
}


EventTabJSONParser.prototype.parse = function(jsonData){
    Log.info("EventTabJSONParser::parse -> Start");
    this.project = this.createProject(jsonData);
    // This Parser expects all years of data to be included in a single file
    this.tab = new EventTab();
    var eventTabRaw = this._findEventsTab(jsonData);
    if (eventTabRaw) {
        this.createTab(eventTabRaw);
    }
    Log.info("EventTabJSONParser::parse -> End");
    
    return this.tab;
}


EventTabJSONParser.prototype.createProject = function(jsonData){
    var projectData = this._findProjectinfo(jsonData);
    var project = new Project();
    //
    project.projectName = this._getProperty(projectData, "projectName", "");
    project.projectCategory = this._getProperty(projectData, "projectCategory", "");
    project.vmixProjectCollectionID = this._getProperty(projectData, "vmixProjectCollectionID", "");
    project.projectLogoLarge = this._getProperty(projectData, "projectLogoLarge", "");
    project.projectLogoSmall = this._getProperty(projectData, "projectLogoSmall", "");
    project.projectLogoHomePage = this._getProperty(projectData, "projectLogoHomePage", "");
    project.crossPromotion = this._getProperty(projectData, "crossPromotion", "");
    project.titleTag = this._getProperty(projectData, "titleTag", "");
    project.metaDescription = this._getProperty(projectData, "metaDescription", "");
    project.metaKeywords = this._getProperty(projectData, "metaKeywords", "");
    
    return project;
}


EventTabJSONParser.prototype.createTab = function(eventTabRaw){
    Log.info(eventTabRaw)
    this.tab.setToday(this._date)
    this.tab.tabType = this._getProperty(eventTabRaw, "tabType", "");
    this.tab.eventType = this.mapEventType(this._getProperty(eventTabRaw, "eventType", ""));
    // HACK: In TeamSite it is "sessions" and the site expects "session"
    if (this.tab.eventType == "sessions") {
        this.tab.eventType = "session";
    }
    // End HACK
    Log.info("tab.eventType:" + this.tab.eventType)
    this.tab.tabName = this._getProperty(eventTabRaw, "tabName", "");
    this.tab.vmixGalleryId = this._getProperty(eventTabRaw, "vmixGalleryId", "");
    this.tab.descriptionCopy = this._getProperty(eventTabRaw, "descriptionCopy", "");
    this.tab.hideEventsTab = (this._getProperty(eventTabRaw, "hideEventsTab", false) == true);
    var rawEvents = ArrayUtils.getArrayFromJSONNode(this._getProperty(eventTabRaw, "event", []));
    if (rawEvents.length > 0) {
        for (var i = 0, event_len = rawEvents.length; i < event_len; i++) {
            var avEvent = this.createEvent(rawEvents[i]);
            avEvent.id = i;
            this.addEventToTab(avEvent);
        }
    }
}
// The Event terminology changed at the last minute. So map the values comming from the data to the
// expected values
EventTabJSONParser.prototype.mapEventType = function(eventType){
    var mappedTo = "";
    var lcEventType = eventType.toLowerCase();
    if (lcEventType == "art") {
        mappedTo = "installation";
    }
    else 
        if (lcEventType == "sessions") {
            mappedTo = "session";
        }
        else {
            mappedTo = "performance";
        }
    return mappedTo;
}

EventTabJSONParser.prototype.createEvent = function(eventData){
    var avEvent = new AVEvent()
    avEvent.eventTourName = this._getProperty(eventData, "eventTourName", "");
    avEvent.eventTourDescription = this._getProperty(eventData, "eventTourDescription", "");
    avEvent.eventInterviewLink = this._getProperty(eventData, "eventInterview", "");
    avEvent.eventTrailerLink = this._getProperty(eventData, "eventTrailer", "");
    avEvent.eventPhotosLink = this._getProperty(eventData, "eventPhotos", "");
    avEvent.eventAudioLink = this._getProperty(eventData, "eventAudio", "");
    var rawEventDates = ArrayUtils.getArrayFromJSONNode(this._getProperty(eventData, "eventDate", []));
    var eventDate
    for (var i = 0, date_len = rawEventDates.length; i < date_len; i++) {
        eventDate = this.createEventDate(rawEventDates[i]);
        //Log.info("EventTabJSONParser::createEvent-> date:"+eventDate.eventTitle+" isPast:"+eventDate.isPast()+" isFuture:"+eventDate.isFuture())
        avEvent.addEventDate(eventDate);
    }
    
    return avEvent
}


EventTabJSONParser.prototype.createEventDate = function(dateData){
    //Log.info("EventTabJSONParser::createEventDate ->"+dateData["eventDetailImage"]);
    var eventDate = new EventDate();
    eventDate.eventId = this._getProperty(dateData, "eventId", "");
    eventDate.eventTitle = this._getProperty(dateData, "eventTitle", "");
    eventDate.eventThumbNailImage = this._getProperty(dateData, "eventThumbNailImage", "");
    eventDate.eventDetailImage = this._getProperty(dateData, "eventDetailImage", "");
    eventDate.eventAddress = this._getProperty(dateData, "eventAddress", "");
    eventDate.eventCity = this._getProperty(dateData, "eventCity", "");
    eventDate.eventState = this._getProperty(dateData, "eventState", "");
    eventDate.eventVenue = this._getProperty(dateData, "eventVenue", "");
    eventDate.eventStartDate = this._getProperty(dateData, "eventStartDate", "");
    eventDate.eventEndDate = this._getProperty(dateData, "eventEndDate", "");
    eventDate.eventTime = this._getProperty(dateData, "eventTime", "");
    eventDate.eventAge = this._getProperty(dateData, "eventAge", "");
    eventDate.eventRsvpUrl = this._getProperty(dateData, "eventRsvpUrl", "");
    eventDate.eventRsvpStartDate = this._getProperty(dateData, "eventRsvpStartDate", "")
	// convert time from 1:30:PM to 13:30 and store it
	var tempRSVPStartTime =  this._getProperty(dateData, "eventRsvpStartTime", "00:00")
	eventDate.eventRsvpStartTime = DateUtils.convertTeamSiteTimeTo24hour(tempRSVPStartTime)
   	//
    eventDate.eventRsvpEndDate = this._getProperty(dateData, "eventRsvpEndDate", "");
	// convert time from 1:30:PM to 13:30 and store it
	var tempRSVPEndTime = this._getProperty(dateData, "eventRsvpEndTime", "00:00");
	eventDate.eventRsvpEndTime = DateUtils.convertTeamSiteTimeTo24hour(tempRSVPEndTime)
	//
    eventDate.eventHideRSVP = (this._getProperty(dateData, "hideUrl", 0) == true);
    eventDate.eventHideDate = (this._getProperty(dateData, "hideEvent", 0) == true);
    eventDate.eventCapacity = this._getIntFromProperty(dateData, "eventCapacity", 0);
    
    //TODO: Replace properties with access methods that call _convertDates when dirty
    eventDate._convertDates();
    
    //
    return eventDate;
}


EventTabJSONParser.prototype.addEventToTab = function(avEvent){
    // if the case of an event spaning years, get the years and add to each years set of events
    var years = avEvent.getYears();
    //Log.info("addEventToTab->"+avEvent.eventTourName+" past:"+avEvent.isPast()+" is Future:"+avEvent.isFuture())
    var currentYear = avEvent._date.getFullYear();
    var theYear;
    var eventYear;
    for (var i = 0, years_len = years.length; i < years_len; i++) {
        theYear = years[i];
        if (!this.tab.hasYearEvent(theYear)) {
            eventYear = new EventYear();
            eventYear.year = theYear;
            this.tab.setYearEvents(theYear, eventYear);
        }
        else {
            eventYear = this.tab.getYearEvents(theYear);
        }
        // Log.info("adding..."+avEvent+" to "+eventYear.year )
        eventYear.addEvent(avEvent);
    }
}


EventTabJSONParser.prototype._getProperty = function(object, propertyString, defaultValue){
    if (object[propertyString]) {
    
        return object[propertyString];
    }
    else {
    
        return defaultValue;
    }
}
EventTabJSONParser.prototype._getIntFromProperty = function(object, propertyString, defaultValue){
    var val
    if (object[propertyString]) {
    
        val = parseInt(object[propertyString]);
        return (isNaN(val)) ? defaultValue : val;
    }
    else {
    
        return defaultValue;
    }
}

EventTabJSONParser.prototype._findProjectinfo = function(data){
    var projectInfo;
    if (data["project"]) {
        if (data.project["projectInformation"]) {
            projectInfo = data.project.projectInformation;
        }
    }
    
    return projectInfo
}


EventTabJSONParser.prototype._findEventsTab = function(data){
    var eventTab
    if (data["project"]) {
        if (data.project["tab"]) {
            var tabs = ArrayUtils.getArrayFromJSONNode(data.project.tab)
            var tab
            for (var i = 0; i < tabs.length; i++) {
                tab = tabs[i]
                if (tab.tabType == "events") {
                    eventTab = tab
                    break;
                }
            }
        }
        else {
            Log.warn("Event data contains no Tab information")
        }
    }
    else {
        Log.warn("Event data contains no Project information")
    }
    
    return eventTab
}


EventTabJSONParser.prototype._convertBool = function(value){
    var bool = false
    if (value == "") {
        bool = false
    }
    else 
        if (value) {
            bool = true
        }
        else {
            bool = false
        }
    
    return bool
}


/***********************************************************************************
 Render Past Performance Event
 ************************************************************************************/
function RenderPastPerformanceEvents(){
}



RenderPastPerformanceEvents.prototype.render = function(events){
    var eventHTML = ""
    if (!events) {
    
        ////Log.error("RenderPastPerformanceEvents::render -> no tab data past in")
        return eventHTML
    }
    if (events.length < 1) {
    
        return eventHTML
    }
    // loop through all events
    for (var i = 0, events_len = events.length; i < events_len; i++) {
        var avEvent = events[i]
        Log.info("Rendering " + avEvent)
        var dates = avEvent.getPastDates()
        if (dates.length < 1) {
            // Log.error("RenderPastPerformanceEvents::render -> " + avEvent + " has no Past Dates, it should have been filtered")
            continue;
        }
        var defaultDate = dates[0]
        //Start Event DIV
        eventHTML += '<div class="event" >'
        //Start Event -> Flyer DIV
        eventHTML += '<div class="flyer">'
        if (defaultDate.eventThumbNailImage.length > 0) {
            eventHTML += '<img src="' + defaultDate.eventThumbNailImage + '"/>'
        }
        else {
            // TODO: test default image support
            eventHTML += '<img src="images/spacer.gif"/>'
        }
        //Log.info("RenderPastPerformanceEvents::render -> defaultDate.showExpandImage():"+defaultDate.showExpandImage())
        if (defaultDate.showExpandImage()) {
            eventHTML += '<a class="expandImage" href="' + defaultDate.eventDetailImage + '">Expand Image</a>'
        }
        else {
            eventHTML += '<a class="expandImage off" href="">Expand Image</a>'
        }
        //DEBUG: line was-> eventHTML += '</div>
        eventHTML += '</div>'
        // End Event - > Flyer DIV
        // Start Event - > EventDetails DIV
        eventHTML += '<div class="eventdetails" >'
        eventHTML += '<h2>' + avEvent.eventTourName + '</h2>'
        eventHTML += '<p>' + avEvent.eventTourDescription + '</p>'
        //
        eventHTML += this.renderDateTitles(dates)
        //Create Date details
        //eventHTML += this.renderDateDetails(dates)
        eventHTML += '<div class="date on">'
        //Log.info("RenderPastPerformanceEvents::render -> avEvent.eventTrailerLink:"+avEvent.eventTrailerLink)
        if (avEvent.eventTrailerLink.length > 0) {
            eventHTML += '<span id="trailerlink" class="eventlinks"><a href="' + avEvent.eventTrailerLink + '">WATCH TRAILER</a></span>'
        }
        if (avEvent.eventInterviewLink.length > 0) {
            eventHTML += '<span id="interviewlink" class="eventlinks"><a href="' + avEvent.eventInterviewLink + '">WATCH INTERVIEWS</a></span>'
        }
        if (avEvent.eventPhotosLink.length > 0) {
            eventHTML += '<span id="photolink" class="eventlinks"><a href="' + avEvent.eventPhotosLink + '">VIEW PHOTOS</a></span>'
        }
        if (avEvent.eventAudioLink.length > 0) {
            eventHTML += '<span id="audiolink"  class="eventlinks"><a href="' + avEvent.eventAudioLink + '">LISTEN TO AUDIO</a></span>'
        }
        //DEBUG: line was-> '</div>'eventAudioLink
        eventHTML += '</div>'
        // End Event - > EventDetails -> Date DIV
        // End Event - > EventDetails DIV
        eventHTML += '</div></div><span class="eventhr">&nbsp;</span>'
        // eventHTML += '</div></div><dir class="hr">&nbsp;</div>'
    }
    
    return eventHTML
}


RenderPastPerformanceEvents.prototype.renderDateTitles = function(dates){
    //var eventHTML = '<div class="dates">Tour Stops:'
    var eventHTML = '<div class="dates"><span class="dataleadin">Tour Stops:</span>'
    for (var j = 0; j < dates.length; j++) {
        var date = dates[j]
        //Log.info("    rendering title for " + date)
        if (date.eventStartDate != date.eventEndDate) {
            //TODO: Correct data to have one time events have the same start and end dates
            // dateString = date.eventStartDate + " - " + date.eventEndDate
            dateString = date.eventStartDate
        }
        else {
            dateString = date.eventStartDate
        }
        eventHTML += '<span class="titlepast">' + date.eventCity + '<br />' + dateString + '<br /><br /></span>'
    }
    eventHTML += '</div>'
    
    return eventHTML
}


RenderPastPerformanceEvents.prototype.renderDateDetails = function(dates){
    var eventHTML = ""
    for (var j = 0; j < dates.length; j++) {
        var date = dates[j]
        //Log.info("    rendering details for " + date)
        if (j == 0) {
            eventHTML += '<div class="date on">'
        }
        else {
            eventHTML += '<div class="date">'
        }
        eventHTML += '<div class="eventTitle">' + date.eventTitle + '</div>'
        eventHTML += '<div class="eventThumbnailImage">' + date.eventThumbNailImage + '</div>'
        if (date.eventStartDate != date.eventEndDate) {
            eventHTML += '<span class="eventStartdate">' + date.eventStartDate + '</span><span class="eventEndDate"> - ' + date.eventEndDate + ' <br /></span>'
        }
        else {
            eventHTML += '<span class="eventStartdate">' + date.eventStartDate + '</span><span class="eventEndDate"><br /></span>'
        }
        eventHTML += '<span class="eventCity">' + date.eventCity + '</span><br /><br />'
        eventHTML += '<span class="eventTime">' + date.eventTime + '</span><br />'
        eventHTML += '<span class="eventVenue">' + date.eventVenue + '</span><br />'
        eventHTML += '<span class="eventVenue">' + date.eventAddress + '</span><br />'
        eventHTML += '<span class="eventVenue">' + date.eventCity + ', ' + date.eventState + '</span><br />'
        if (date.showRSVP()) {
            eventHTML += '<a class="rsvp" href="#' + date.eventTitle + '">Click to RSVP</a>'
        }
        eventHTML += '</div>'
    }
    //eventHTML += '</div></div>'
    eventHTML += '</div></div><span class="eventhr">&nbsp;</span>'
    
    return eventHTML
}


/***********************************************************************************
 Render Upcoming Performance Event
 ************************************************************************************/
function RenderUpcomingPerformanceEvents(){
}



RenderUpcomingPerformanceEvents.prototype.render = function(events){
    var eventHTML = ""
    if (!events) {
    
        ////Log.error("renderUpcomingPerformanceEvents::render -> no tab data past in")
        return eventHTML
    }
    if (events.length < 1) {
    
        // eventHTML = getnoUpcomingEvents()
        return eventHTML
    }
    // loop through all events
    for (var i = 0, events_len = events.length; i < events_len; i++) {
        var avEvent = events[i]
        //Log.info("Rendering " + avEvent)
        var dates = avEvent.getFutureDates()
        if (dates.length < 1) {
            Log.error("renderUpcoming::render -> " + avEvent + " has no Future Dates, it should have been filtered")
            continue;
        }
        var defaultDate = dates[0]
        //Start Event DIV
        eventHTML += '<div class="event" >'
        //Start Event -> Flyer DIV
        eventHTML += '<div class="flyer">'
        if (defaultDate.eventThumbNailImage.length > 0) {
            eventHTML += '<img src="' + defaultDate.eventThumbNailImage + '"/>'
        }
        else {
            // TODO: test default image support
            eventHTML += '<img src="images/spacer.gif"/>'
        }
        //Log.info("RenderUpcomingPerformanceEvents::render -> defaultDate.showExpandImage():"+defaultDate.showExpandImage())
        if (defaultDate.showExpandImage()) {
            eventHTML += '<a class="expandImage" href="' + defaultDate.eventDetailImage + '">Expand Image</a>'
        }
        else {
            eventHTML += '<a class="expandImage off" href="">Expand Image</a>'
        }
        eventHTML += '</div>'
        // End Event - > Flyer DIV
        // Start Event - > EventDetails DIV
        eventHTML += '<div class="eventdetails" >'
        eventHTML += '<h2>' + avEvent.eventTourName + '</h2>'
        eventHTML += '<p>' + avEvent.eventTourDescription + '</p>'
        //
        eventHTML += this.renderDateTitles(dates, avEvent.id)
        //Create Date details
        eventHTML += this.renderDateDetails(dates, avEvent.id)
        // End Event - > EventDetails -> Date DIV
        // End Event - > EventDetails DIV
        // eventHTML += '</div>'
        eventHTML += '</div><span class="eventhr">&nbsp;</span>'
    }
    
    return eventHTML
}


RenderUpcomingPerformanceEvents.prototype.renderDateTitles = function(dates, eventId){
    if (isNaN(eventId)) {
        eventId = 999;
    }
    var eventHTML = '<div class="dates"><span class="dataleadin">Tour Stops:</span>'
    for (var j = 0; j < dates.length; j++) {
        var date = dates[j]
        var fullId = eventId + '-' + date.id
        //Log.info("    rendering title for " + date)
        if (date.eventStartDate != date.eventEndDate) {
            //Todo: Change data to single date
            //dateString = date.eventStartDate + " - " + date.eventEndDate
            dateString = date.eventStartDate
        }
        else {
            dateString = date.eventStartDate
        }
        eventHTML += '<a href="#' + j + ',' + fullId + '"'
        if (j == 0) {
            eventHTML += ' class="on"'
        }
        eventHTML += '>' + date.eventCity + '<br />' + dateString + '</a>'
    }
    eventHTML += '</div>'
    
    return eventHTML
}


RenderUpcomingPerformanceEvents.prototype.renderDateDetails = function(dates, eventId){
    var eventHTML = ""
    for (var j = 0; j < dates.length; j++) {
        var date = dates[j]
        var fullId = eventId + '-' + date.id
        //Log.info("    rendering details for " + date)
        if (j == 0) {
            eventHTML += '<div class="date on">'
        }
        else {
            eventHTML += '<div class="date">'
        }
        eventHTML += '<div class="eventTitle">' + date.eventTitle + '</div>'
        eventHTML += '<div class="eventThumbnailImage">' + date.eventThumbNailImage + '</div>'
        /*
         if (date.eventStartDate != date.eventEndDate)
         {
         eventHTML += '<span class="eventStartdate">' + date.eventStartDate + '</span><span class="eventEndDate"> - ' + date.eventEndDate + ' <br /></span>'
         }
         else
         {
         eventHTML += '<span class="eventStartdate">' + date.eventStartDate + '</span><span class="eventEndDate"><br /></span>'
         }
         eventHTML += '<span class="eventCity">' + date.eventCity + '</span><br /><br />'
         */
        eventHTML += '<span class="eventTime">' + date.eventTime + '</span><br />'
        eventHTML += '<span class="eventVenue">' + date.eventVenue + '</span><br />'
        eventHTML += '<span class="eventVenue">' + date.eventAddress + '</span><br />'
        eventHTML += '<span class="eventVenue">' + date.eventCity + ', ' + date.eventState + '</span><br />'
        if (date.eventAge != "") {
            eventHTML += '<br /><span class="eventVenue">Ages:' + date.eventAge + '</span><br />'
        }
        if (date.showRSVP()) {
            eventHTML += '<a  href="#' + fullId + '">Click to RSVP</a>'
        } else if (date.showClosedRSVP()){
			Log.info("showing Closed RSVP for "+date.eventTitle)
			eventHTML += '<a  href="#' + fullId + '">Click to RSVP</a>'
		}
        eventHTML += '</div>'
    }
    eventHTML += '</div>'
    
    return eventHTML
}


/***********************************************************************************
 Render Upcoming Session Events
 ************************************************************************************/
function RenderUpcomingSessionEvents(){
}



RenderUpcomingSessionEvents.prototype.render = function(events){
    var eventHTML = ""
    if (!events) {
    
        ////Log.error("renderUpcomingPerformanceEvents::render -> no tab data past in")
        return eventHTML
    }
    if (events.length < 1) {
    
        // eventHTML = getnoUpcomingEvents()
        return eventHTML
    }
    // loop through all events
    for (var i = 0, events_len = events.length; i < events_len; i++) {
        var avEvent = events[i]
        Log.info("Rendering " + avEvent)
        var dates = avEvent.getFutureDates()
        if (dates.length < 1) {
            Log.error("renderUpcoming::render -> " + avEvent + " has no Future Dates, it should have been filtered")
            continue;
        }
        var defaultDate = dates[0]
        //Start Event DIV
        eventHTML += '<div class="event" >'
        //Start Event -> Flyer DIV
        eventHTML += '<div class="flyer">'
        if (defaultDate.eventThumbNailImage.length > 0) {
            eventHTML += '<img src="' + defaultDate.eventThumbNailImage + '"/>'
        }
        else {
            // TODO: test default image support
            eventHTML += '<img src="images/spacer.gif"/>'
        }
        //Log.info("RenderUpcomingPerformanceEvents::render -> defaultDate.showExpandImage():"+defaultDate.showExpandImage())
        if (defaultDate.showExpandImage()) {
            eventHTML += '<a class="expandImage" href="' + defaultDate.eventDetailImage + '">Expand Image</a>'
        }
        else {
            eventHTML += '<a class="expandImage off" href="">Expand Image</a>'
        }
        eventHTML += '</div>'
        // End Event - > Flyer DIV
        // Start Event - > EventDetails DIV
        eventHTML += '<div class="eventdetails" >'
        eventHTML += '<h3>' + avEvent.eventTourName + '</h3>'
        eventHTML += '<p>' + avEvent.eventTourDescription + '</p>'
        //
        eventHTML += this.renderDateTitles(dates, avEvent.id)
        //Create Date details
        eventHTML += this.renderDateDetails(dates, avEvent.id)
        // End Event - > EventDetails -> Date DIV
        // End Event - > EventDetails DIV
        //eventHTML += '</div>'
        eventHTML += '</div><span class="eventhr">&nbsp;</span>'
    }
    
    return eventHTML
}


RenderUpcomingSessionEvents.prototype.renderDateTitles = function(dates, eventId){
    if (isNaN(eventId)) {
        eventId = 999;
    }
    //var eventHTML = '<div class="dates">Events:'
    var eventHTML = '<div class="dates"><span class="dataleadin">Events:</span>'
    for (var j = 0; j < dates.length; j++) {
        var date = dates[j]
        var fullId = eventId + '-' + date.id
        //Log.info("    rendering title for " + date)
        if (date.eventStartDate != date.eventEndDate) {
            dateString = date.eventStartDate + " - " + date.eventEndDate
        }
        else {
            dateString = date.eventStartDate
        }
        eventHTML += '<br /><a href="#' + j + ',' + fullId + '"'
        if (j == 0) {
            eventHTML += ' class="on"'
        }
        eventHTML += '>' + date.eventCity + '<br />' + dateString + '</a>'
    }
    eventHTML += '</div>'
    
    return eventHTML
}


RenderUpcomingSessionEvents.prototype.renderDateDetails = function(dates, eventId){
    var eventHTML = ""
    for (var j = 0; j < dates.length; j++) {
        var date = dates[j]
        var fullId = eventId + '-' + date.id
        //Log.info("    rendering details for " + date)
        if (j == 0) {
            eventHTML += '<div class="date on">'
        }
        else {
            eventHTML += '<div class="date">'
        }
        eventHTML += '<span class="eventTitle">' + date.eventTitle + '</span><br />'
        eventHTML += '<div class="eventThumbnailImage">' + date.eventThumbNailImage + '</div>'
        if (date.eventStartDate != date.eventEndDate) {
            eventHTML += '<span class="eventStartdate">' + date.eventStartDate + '</span><span class="eventEndDate"> - ' + date.eventEndDate + ' <br /></span>'
        }
        else {
            eventHTML += '<span class="eventStartdate">' + date.eventStartDate + '</span><span class="eventEndDate"><br /></span>'
        }
        eventHTML += '<span class="eventTime">' + date.eventTime + '</span><br />'
        eventHTML += '<span class="eventVenue">' + date.eventVenue + '</span><br />'
        eventHTML += '<span class="eventVenue">' + date.eventAddress + '</span><br />'
        eventHTML += '<span class="eventCity">' + date.eventCity + ', ' + date.eventState + '</span><br />'
        if (date.showRSVP()) {
            eventHTML += '<a  href="#' + fullId + '">Click to RSVP</a>'
        }
        eventHTML += '</div>'
    }
    eventHTML += '</div>'
    
    return eventHTML
}


/***********************************************************************************
 Base Event Renderer
 ************************************************************************************/
/* TODO: Abstract a Base Render to DRY the Render Calsses */
/*
 function BaseEventRenderer(subClass)
 {
 this.subClass = subClass;
 }
 BaseEventRenderer.prototype.render = function(events)
 {
 var eventHTML = ""
 if (!events)
 {
 
 ////Log.error("renderUpcomingPerformanceEvents::render -> no tab data past in")
 return eventHTML
 }
 if (events.length < 1)
 {
 
 // eventHTML = getnoUpcomingEvents()
 return eventHTML
 }
 // loop through all events
 for (var i = 0, events_len = events.length; i < events_len; i++)
 {
 var avEvent = events[i]
 eventHTML = this.renderEvent(avEvent)
 }
 }
 BaseEventRenderer.renderEvent= function(avEvent)
 {
 if (this.subClass)
 {
 return this.subClass.renderEvent(avEvent)
 } else
 {
 return this.defaultRenderEvent(avEvent)
 }
 }
 //BaseEventRenderer.renderEvent= function(avEvent)
 {
 
 }
 // */
/***********************************************************************************
 Render Past Installation Event
 ************************************************************************************/
function RenderPastInstallationEvents(){
}



RenderPastInstallationEvents.prototype.render = function(events){
    var eventHTML = ""
    if (!events) {
    
        ////Log.error("renderUpcomingPerformanceEvents::render -> no tab data past in")
        return eventHTML
    }
    if (events.length < 1) {
    
        // eventHTML = getnoUpcomingEvents()
        return eventHTML
    }
    // loop through all events
    for (var i = 0, events_len = events.length; i < events_len; i++) {
        var avEvent = events[i]
        //Log.info("Rendering " + avEvent)
        var dates = avEvent.getPastDates()
        if (dates.length < 1) {
            Log.warn("RenderPastInstallationEvents::render -> " + avEvent + " has no Future Dates, it should have been filtered")
            continue;
        }
        var defaultDate = dates[0]
        //Start Event DIV
        eventHTML += '<div class="event" >'
        //Start Event -> Flyer DIV
        eventHTML += '<div class="flyer">'
        if (defaultDate.eventThumbNailImage.length > 0) {
            eventHTML += '<img src="' + defaultDate.eventThumbNailImage + '"/>'
        }
        else {
            // TODO: test default image support
            eventHTML += '<img src="images/spacer.gif"/>'
        }
        //Log.info("RenderPastInstallationEvents::render -> defaultDate.showExpandImage():"+defaultDate.showExpandImage())
        if (defaultDate.showExpandImage()) {
            // eventHTML += '<div class="expandlink"><a class="expandImage" href="' + defaultDate.eventDetailImage + '">Expand Image</a></div>'
            eventHTML += '<a class="expandImage" href="' + defaultDate.eventDetailImage + '">Expand Image</a>'
        }
        else {
            eventHTML += '<a class="expandImage off" href="">Expand Image</a>'
        }
        //	eventHTML += '</div>'
        eventHTML += '</div>'
        // End Event - > Flyer DIV
        // Start Event - > EventDetails DIV
        eventHTML += '<div class="eventdetails" >'
        eventHTML += '<h3>' + defaultDate.eventCity + ", " + defaultDate.eventState + '</h3>'
        eventHTML += '<h2>' + avEvent.eventTourName + '</h2>'
        eventHTML += '<p>' + avEvent.eventTourDescription + '</p>'
        // Start Event - > EventDetails -> Dates DIV
        eventHTML += this.renderDateTitles(dates, avEvent.id)
        //Create Date details
        //eventHTML += this.renderDateDetails(dates)
        eventHTML += '<div class="date on">'
        //Log.info("RenderPastPerformanceEvents::render -> avEvent.eventTrailerLink:"+avEvent.eventTrailerLink)
        if (avEvent.eventTrailerLink.length > 0) {
            eventHTML += '<span id="trailerlink" class="eventlinks"><a href="' + avEvent.eventTrailerLink + '">WATCH TRAILER</a></span>'
        }
        if (avEvent.eventInterviewLink.length > 0) {
            eventHTML += '<span id="interviewlink" class="eventlinks"><a href="' + avEvent.eventInterviewLink + '">WATCH INTERVIEWS</a></span>'
        }
        if (avEvent.eventPhotosLink.length > 0) {
            eventHTML += '<span id="photolink" class="eventlinks"><a href="' + avEvent.eventPhotosLink + '">VIEW PHOTOS</a></span>'
        }
        if (avEvent.eventAudioLink.length > 0) {
            eventHTML += '<span id="audiolink"  class="eventlinks"><a href="' + avEvent.eventAudioLink + '">LISTEN TO AUDIO</a></span>'
        }
        //DEBUG: line was-> '</div>'
        eventHTML += '</div>'
        // End Event - > EventDetails -> Date DIV
        // End Event - > EventDetails DIV
        eventHTML += '</div></div><span class="eventhr">&nbsp;</span>'
        // eventHTML += '</div></div><dir class="hr">&nbsp;</div>'
    }
    
    return eventHTML
}


RenderPastInstallationEvents.prototype.renderDateTitles = function(dates, eventId){
    /*
     if (isNaN(eventId))
     {
     eventId = 999;
     }
     var eventHTML = '<div class="dates">Events:<div class="titlepast">'
     for (var j = 0; j < dates.length; j++)
     {
     var date = dates[j]
     var fullId = eventId + '-' + date.id
     //eventHTML += '<br />' + date.eventTitle + '<br />'
     eventHTML +=  date.eventTitle +  '<br /><br />'
     }
     eventHTML += '</div></div>'
     */
    var eventHTML = '<div class="dates">&nbsp;</div>'
    return eventHTML
}


RenderPastInstallationEvents.prototype.renderDateDetails = function(dates, eventId){
    var eventHTML = ""
    for (var j = 0; j < dates.length; j++) {
        var date = dates[j]
        var fullId = eventId + '-' + date.id
        //Log.info("    rendering details for " + date)
        if (j == 0) {
            eventHTML += '<div class="date on">'
        }
        else {
            eventHTML += '<div class="date">'
        }
        eventHTML += '<div class="eventTitle">' + date.eventTitle + '</div>'
        eventHTML += '<div class="eventThumbnailImage">' + date.eventThumbNailImage + '</div>'
        if (date.eventStartDate != date.eventEndDate) {
            eventHTML += '<span class="eventStartdate">' + date.eventStartDate + '</span><span class="eventEndDate"> - ' + date.eventEndDate + ' <br /></span>'
        }
        else {
            eventHTML += '<span class="eventStartdate">' + date.eventStartDate + '</span><span class="eventEndDate"><br /></span>'
        }
        eventHTML += '<span class="eventCity">' + date.eventCity + '</span><br /><br />'
        eventHTML += '<span class="eventTime">' + date.eventTime + '</span><br />'
        eventHTML += '<span class="eventVenue">' + date.eventVenue + '</span><br />'
        eventHTML += '<span class="eventVenue">' + date.eventAddress + '</span><br />'
        eventHTML += '<span class="eventVenue">' + date.eventCity + ', ' + date.eventState + '</span><br />'
        if (date.showRSVP()) {
            eventHTML += '<a  href="#' + fullId + '">Click to RSVP</a>'
        }
        eventHTML += '</div>'
    }
    //eventHTML += '</div>'
    eventHTML += '</div>'
    
    return eventHTML
}


/***********************************************************************************
 Render Upcoming Performance Event
 ************************************************************************************/
function RenderUpcomingInstallationEvents(){
}



RenderUpcomingInstallationEvents.prototype.render = function(events){
    var eventHTML = ""
    if (!events) {
    
        ////Log.error("renderUpcomingPerformanceEvents::render -> no tab data past in")
        return eventHTML
    }
    if (events.length < 1) {
    
        // eventHTML = getnoUpcomingEvents()
        return eventHTML
    }
    // loop through all events
    for (var i = 0, events_len = events.length; i < events_len; i++) {
        var avEvent = events[i]
        //Log.info("Rendering " + avEvent)
        var dates = avEvent.getFutureDates()
        if (dates.length < 1) {
            Log.warn("renderUpcoming::render -> " + avEvent + " has no Future Dates, it should have been filtered")
            continue;
        }
        var defaultDate = dates[0]
        //Start Event DIV
        eventHTML += '<div class="event" >'
        //Start Event -> Flyer DIV
        eventHTML += '<div class="flyer">'
        if (defaultDate.eventThumbNailImage.length > 0) {
            eventHTML += '<img src="' + defaultDate.eventThumbNailImage + '"/>'
        }
        else {
            // TODO: test default image support
            eventHTML += '<img src="images/spacer.gif"/>'
        }
        //Log.info("RenderUpcomingPerformanceEvents::render -> defaultDate.showExpandImage():"+defaultDate.showExpandImage())
        if (defaultDate.showExpandImage()) {
            eventHTML += '<a class="expandImage" href="' + defaultDate.eventDetailImage + '">Expand Image</a>'
        }
        else {
            eventHTML += '<a class="expandImage off" href="">Expand Image</a>'
        }
        eventHTML += '</div>'
        // End Event - > Flyer DIV
        // Start Event - > EventDetails DIV
        eventHTML += '<div class="eventdetails" >'
        eventHTML += '<h3>' + defaultDate.eventCity + ", " + defaultDate.eventState + '</h3>'
        eventHTML += '<h2>' + avEvent.eventTourName + '</h2>'
        eventHTML += '<p>' + avEvent.eventTourDescription + '</p>'
        // Start Event - > EventDetails -> Dates DIV
        eventHTML += this.renderDateTitles(dates, avEvent.id)
        // Start Event - > EventDetails -> Date DIV
        eventHTML += this.renderDateDetails(dates, avEvent.id)
        // End Event - > EventDetails -> Date DIV
        // End Event - > EventDetails DIV
        eventHTML += '</div><span class="eventhr">&nbsp;</span>'
    }
    
    return eventHTML
}


RenderUpcomingInstallationEvents.prototype.renderDateTitles = function(dates, eventId){
    if (isNaN(eventId)) {
        eventId = 999;
    }
    //var eventHTML = '<div class="dates">Events:'
    var eventHTML = '<div class="dates"><span class="dataleadin">Events:</span>'
    for (var j = 0; j < dates.length; j++) {
        var date = dates[j]
        var fullId = eventId + '-' + date.id
        eventHTML += '<a href="#' + j + ',' + fullId + '"'
        if (j == 0) {
            eventHTML += ' class="on"'
        }
        eventHTML += '>' + date.eventTitle + '</a><br />'
    }
    eventHTML += '</div>'
    
    return eventHTML
}


RenderUpcomingInstallationEvents.prototype.renderDateDetails = function(dates, eventId){
    var eventHTML = ""
    for (var j = 0; j < dates.length; j++) {
        var date = dates[j]
        var fullId = eventId + '-' + date.id
        //Log.info("    rendering details for " + date)
        if (j == 0) {
            eventHTML += '<div class="date on">'
        }
        else {
            eventHTML += '<div class="date">'
        }
        eventHTML += '<div class="eventTitle">' + date.eventTitle + '</div>'
        eventHTML += '<div class="eventThumbnailImage">' + date.eventThumbNailImage + '</div>'
        if (date.eventStartDate != date.eventEndDate) {
            eventHTML += '<span class="eventStartdate">' + date.eventStartDate + '</span><span class="eventEndDate"> - ' + date.eventEndDate + ' <br /></span>'
        }
        else {
            eventHTML += '<span class="eventStartdate">' + date.eventStartDate + '</span><span class="eventEndDate"><br /></span>'
        }
        /* eventHTML += '<span class="eventCity">' + date.eventCity + '</span><br /><br />'*/
        eventHTML += '<span class="eventTime">' + date.eventTime + '</span><br />'
        eventHTML += '<span class="eventVenue">' + date.eventVenue + '</span><br />'
        eventHTML += '<span class="eventVenue">' + date.eventAddress + '</span><br />'
        eventHTML += '<span class="eventVenue">' + date.eventCity + ', ' + date.eventState + '</span><br />'
        if (date.showRSVP()) {
            eventHTML += '<a  href="#' + fullId + '">Click to RSVP</a>'
        }
        eventHTML += '</div>'
    }
    //eventHTML += '</div>'
    eventHTML += '</div>'
    
    return eventHTML
}


/****************************
 Event Display Options Class
 *****************************/
function EventDisplayOptions(year, timeFrame){
    this.year = ""
    if (year) {
        this.year = year
    }
    this.timeFrame = "past"
    // past, current, or future
    if (timeFrame) {
        this.setTimeFrame(timeFrame)
    }
    this.state = "all"
}



EventDisplayOptions.prototype.setTimeFrame = function(str){
    switch (str) {
        case "current":
        case "future":
        case "past":
        case "notpast":
            this.timeFrame = str
            break;
        default:
            Log.warn("EventDisplayOptions::setTimeframe -> value:" + str + " is not a valid option")
            this._timeFrame = 'past'
    }
}


EventDisplayOptions.prototype.setState = function(stateFilter){
    this.state = stateFilter
}


function States(){
    this.stateMap = {}
    this.stateAbbrMap = {}
    this.dataProvider = []
}



States.prototype._createStates = function(){
    var str = "Alabama,Alaska,Arizona,Arkansas,California,Colorado,Connecticut,Delaware,District of Columbia,Florida,"
    str += "Georgia,Hawaii,Idaho,Illinois,Indiana,Iowa,Kansas,Kentucky,Louisiana,Maine,Maryland,Massachusetts,"
    str += "Michigan,Minnesota,Mississippi,Missouri,Montana,Nebraska,Nevada,New Hampshire,New Jersey,New Mexico,"
    str += "New York,North Carolina,North Dakota,Ohio,Oklahoma,Oregon,Pennsylvania,Rhode Island,South Carolina,"
    str += "South Dakota,Tennessee,Texas,Utah,Vermont,Virginia,Washington,West Virginia,Wisconsin,Wyoming"
    this.stateNames = str.split(",")
    str = "AL,AK,AZ,AR,CA,CO,CT,DE,DC,FL,GA,HI,ID,IL,IN,IA,KS,KY,LA,ME,MD,MA,MI,MN,MS,MO,MT,NE,NV,NH,NJ,NM,NY,NC,ND,OH,OK,OR,PA,RI,SC,SD,TN,TX,UT,VT,VA,WA,WV,WI,WY"
    this.stateAbbr = str.split(",")
    var aState
    var abbr
    for (var i = 0, state_len = this.stateNames.length; i < state_len; i++) {
        aState = this.stateNames[i]
        abbr = this.stateAbbr[i]
        this.dataProvider.push({
            label: aState,
            data: abbr
        })
        this.stateAbbrMap[abbr] = aState
    }
}


States.prototype.getNameFromAbbr = function(abbr){
    var name = ""
    if (this.stateAbbrMap[abbr]) {
        name = this.stateAbbrMap[abbr];
    }
    
    return name;
}


States.prototype.getDataProvider = function(){

    return this.dataProvider;
}


States.prototype.isValidAbbr = function(abbr){

    return (this.getNameFromAbbr(abbr).length > 0)
}


/****************************
 Event Results
 *****************************/
function EventResults(){
    this.projectType = ""
    this.projectName = ""
    this.titleTag = ""
    this.year = ""
    this.timeFrame = ""
    this.events = []
}



/****************************
 ScionAv Event Class
 *****************************/
function Project(){
    this.projectName = ""
    this.projectCategory = ""
    this.vmixProjectCollectionID = ""
    this.projectLogoLarge = ""
    this.projectLogoSmall = ""
    this.projectLogoHomePage = ""
    this.crossPromotion = ""
    this.titleTag = ""
    this.metaDescription = ""
    this.metaKeywords = ""
}



Project.prototype.toString = function(){

    return '[Project name="' + this.projectName + '" ]';
}


function EventTab(){
    this._date = DateUtils.getToday();
    this._isReady = false;
    this.tabType = ""
    this.eventType = ""
    this.tabName = ""
    this.vmixGalleryId = ""
    this.descriptionCopy = ""
    this.hideEventsTab = false;
    this.years = {}
    this.current
    //this._dirty = false
}



EventTab.prototype.isReady = function(){

    return (this.years.length > 0)
}


EventTab.prototype.getAvailableYears = function(){
    var availableYears = []
    for (var i in this.years) {
        availableYears.push(i)
    }
    
    return availableYears
}


EventTab.prototype.setToday = function(date){
    if (ObjectUtils.isDate(date)) {
        this._date = date;
        for (var i in this.years) {
            this.years[i].setToday(this._date)
        }
    }
}


EventTab.prototype.setYearEvents = function(yearStr, eventYear){
    this.years[yearStr] = eventYear
}


EventTab.prototype.getYearEvents = function(yearStr){
    var eventYear
    if (this.years[yearStr]) {
        eventYear = this.years[yearStr]
    }
    
    return eventYear
}


EventTab.prototype.hasYearEvent = function(yearStr){
    var hasYear = false
    if (this.years[yearStr]) {
        hasYear = true;
    }
    
    return hasYear
}


EventTab.prototype.getAvailableYears = function(yearStr){
    var availableYears = []
    for (var i in this.years) {
        availableYears.push(i)
    }
    availableYears.sort()
    availableYears.reverse()
    
    //Log.info("Event.getAvailableYears=>" + availableYears)
    return availableYears
}


EventTab.prototype.toString = function(){
    var yearsMsg = ""
    for (var i in this.years) {
        yearsMsg += this.years[i] + ", ";
    }
    
    return '[EventTab name="' + this.tabName + '" type="' + this.tabType + '" eventType="' + this.eventType + '" years="' + yearsMsg + '" ]';
}


function EventYear(){
    this.year = "";
    this._date = DateUtils.getToday();
    this._events = [];
    this._past = [];
    this._current = [];
    this._future = [];
    this._dirty = true;
}



EventYear.prototype.hasVisibleEvents = function(){

    return (this._past.length + this._future.length + this._current.length) > 0
}


EventYear.prototype.addEvent = function(anEvent){
    if (anEvent) {
        this._dirty = true;
        anEvent.id = this._events.length
        this._events.push(anEvent);
    }
}


EventYear.prototype.getEvent = function(id){
    var avEvent
    for (var i = 0, event_len = this._events.length; i < event_len; i++) {
        if (this._events[i].id == id) {
            avEvent = this._events[i]
        }
    }
    
    return avEvent
}

EventYear.prototype.getEventDateByEventId = function(id){
    var eventDate
    var evt
    var dates
    var date
    for (var i = this._events.length - 1; i > -1; i--) {
        evt = this._events[i]
        Log.info("checking event:" + evt.eventTourName)
        for (var j = 0, date_len = evt.dates.length; j < date_len; j++) {
            date = evt.dates[j]
            Log.info("checking date:" + date.eventTitle + " id:" + date.eventId)
            if (date.eventId == id) {
                eventDate = date
                break;
            }
        }
        if (eventDate) {
            break;
        }
    }
    
    return eventDate
}

EventYear.prototype.setToday = function(date){
    this._dirty = true;
    if (ObjectUtils.isDate(date)) {
        this._date = date;
        if (this._events.length > 0) {
            for (var i = 0, event_len = this._events.length; i < event_len; i++) {
                this._events[i].setToday(this._date);
            }
        }
    }
}


EventYear.prototype.getCurrent = function(){
    this._updateData();
    
    return this._current
}


EventYear.prototype.getFuture = function(){
    this._updateData();
    
    return this._future
}


EventYear.prototype.getPast = function(){
    this._updateData();
    
    return this._past
}


EventYear.prototype.getEventByState = function(stateAbbr){
    // TODO turn states in to a static object
    Log.info("EventYear::getEventByState " + stateAbbr)
    /*
     var states = new States()
     if (stateAbbr != "all")
     {
     if (!states.isValidAbbr(stateAbbr))
     {
     stateAbbr = "all"
     }
     }
     */
    var notPast = this.getFuture()
    var filtered = []
    if (stateAbbr == "all") {
        //Log.info("EventYear::getEventByState getting All")
        filtered = notPast
    }
    else {
        //Log.info("EventYear::getEventByState getting"+ stateAbbr)
        var eventState
        var avEvent
        var eventDate
        for (var i = 0, notPast_len = notPast.length; i < notPast_len; i++) {
            avEvent = notPast[i]
            if (avEvent.hasFutureDates()) {
                eventDate = avEvent.getFutureDates()[0]
                // trim whitespace
                eventState = eventDate.eventState.toUpperCase()
                eventState = eventState.replace(/^\s+|\s+$/g, "");
                if (eventState == stateAbbr) {
                    filtered.push(avEvent)
                }
            }
        };
        
            }
    //
    // filtered.sort(EventDate.stateAbbr)
    Log.info(filtered)
    filtered.sort(AVEvent.sortTourName)
    Log.info(filtered)
    //
    
    return filtered
}
/*
 EventYear.sortByAbbr = function(abbrA, abbrB){
 var states = new States()
 var fullA = states.getNameFromAbbr(abbrA)
 var fullB = states.getNameFromAbbr(abbrB)
 return fullA -fullB
 }
 */
EventYear.prototype._updateData = function(){
    if (this._dirty) {
        var avEvent
        this._past = []
        this._current = []
        this._future = []
        // Loop thru events and put in categories
        for (var i = 0, event_len = this._events.length; i < event_len; i++) {
            avEvent = this._events[i]
            if (avEvent.isReady()) {
                if (avEvent.isPast()) {
                    this._past.push(avEvent)
                }
                if (avEvent.isFuture()) {
                    this._future.push(avEvent)
                }
            }
        }
        //sort events by date
        this._past.sort(AVEvent.startDatePast)
        this._future.sort(AVEvent.startDateFuture)
        // take the first future event and put in current
        if (this._future.length > 0) {
            this._current.push(this._future[0])
            //this._future.shift()
        }
        this._dirty = false
    }
}


EventYear.prototype.toString = function(){
    this._updateData();
    
    return '[EventYear year="' + this.year + '" events="' + this._events + '"]'
}


function AVEvent(){
    this._date = DateUtils.getToday();
    this.id = -1
    this._isReady = false;
    this._eventType = "";
    this._isDirty = true;
    this.eventTourName = "";
    this.eventTourDescription = "";
    this.eventInterviewLink = ""
    this.eventTrailerLink = ""
    this.eventPhotosLink = ""
    this.eventAudioLink = ""
    this.dates = [];
    this.pastDates = []
    this.futureDates = []
    this.years = []
    this._isVisible = false
}



AVEvent.prototype.setToday = function(date){
    if (ObjectUtils.isDate(date)) {
        this._date = date;
        if (this.dates.length > 0) {
            for (var i = 0; i < this.dates.length; i++) {
                this.dates[i].setToday(this._date);
            }
        }
    }
    this._dirty = true
}


AVEvent.prototype.isReady = function(){
    if (this.dates.length > 0) {
        this._isReady = true;
    }
    else {
        this._isReady = false;
    }
    
    return this._isReady;
}


AVEvent.prototype.getEventType = function(){

    //TODO: this has been moved to tab -> remove next iteration
    return this._eventType;
}


AVEvent.prototype.addEventDate = function(eventDate){
    if (eventDate) {
        if (eventDate.isReady()) {
            eventDate.setToday(this._date)
            eventDate.id = this.dates.length
            this.dates.push(eventDate);
        }
    }
    this._dirty = true
}


AVEvent.prototype.getEventDate = function(id){
    var eventDate
    for (var i = 0, dates_len = this.dates.length; i < dates_len; i++) {
        if (this.dates[i].id == id) {
            eventDate = this.dates[i]
            break;
        }
    }
    
    return eventDate
}


AVEvent.prototype.isPast = function(){

    // note an event could have dates in the past and future
    // if an event needs to be completely in the past to show in the past events then
    // it should be: this.hasPastDates() && !this.hasFutureDates()
    return this.hasPastDates()
}


AVEvent.prototype.isFuture = function(){

    return this.hasFutureDates()
}


AVEvent.prototype.isVisible = function(){
    this._updateData();
    
    return this._isVisible
}


AVEvent.prototype.hasPastDates = function(){
    this._updateData();
    
    return this.pastDates.length > 0;
}


AVEvent.prototype.hasFutureDates = function(){
    this._updateData();
    
    return this.futureDates.length > 0;
}


AVEvent.prototype.getPastDates = function(){
    this._updateData();
    
    return this.pastDates;
}


AVEvent.prototype.getPreviousDate = function(){
    var ed;
    if (this.hasPastDates()) {
        ed = this.pastDates[0];
    }
    else {
        ed = new EventDate();
        ed.eventHideDate = true;
    }
    
    return ed
}


AVEvent.prototype.getNextDate = function(){
    var ed
    if (this.hasFutureDates()) {
        ed = this.futureDates[0];
    }
    else {
        ed = new EventDate();
        ed.eventHideDate = true;
    }
    
    return ed;
}


AVEvent.prototype.getFutureDates = function(){
    this._updateData();
    
    return this.futureDates;
}


AVEvent.prototype.getYears = function(){
    this._updateData();
    
    // return copy
    return this.years.slice(0);
}


AVEvent.prototype.toString = function(){

    return '{AVEvent name="' + this.eventTourName + '" dates="' + this.dates.toString() + '"}'
}


AVEvent.prototype._updateData = function(){
    if (this._dirty) {
        //Log.info("AVEvent::_updateData")
        this._dirty = false;
        this.years = this._getYears()
        this.pastDates = ArrayUtils.filter(this.dates, EventFilters.pastAndVisible);
        this.pastDates.sort(EventDate.startDatePast)
        this.futureDates = ArrayUtils.filter(this.dates, EventFilters.futureAndVisible);
        this.futureDates.sort(EventDate.startDateFuture)
        this._isVisible = ArrayUtils.some(this.dates, EventFilters.isVisible);
    }
}


AVEvent.prototype._getYears = function(){
    var yearsObj = {}
    var eventDate
    var theYear
    var theCurrentYearInt = parseInt(this._date.getFullYear())
    for (var i = 0, dates_len = this.dates.length; i < dates_len; i++) {
        eventDate = this.dates[i]
        if (eventDate["event_s_Date"]) {
            theYear = eventDate.event_s_Date.getFullYear()
            // put all events in the future in current year
            if (parseInt(theYear) > theCurrentYearInt) {
                theYear = this._date.getFullYear()
            }
            yearsObj[theYear] = 1
        }
        if (eventDate["event_e_Date"]) {
            // put all events in the future in current year
            theYear = eventDate.event_e_Date.getFullYear()
            if (parseInt(theYear) > theCurrentYearInt) {
                theYear = this._date.getFullYear()
            }
            yearsObj[theYear] = 1
        }
    }
    var years = []
    for (var j in yearsObj) {
        years.push(j)
    }
    
    return years
}


AVEvent.startDateFuture = function(a, b){
    var aDate = a.getNextDate()
    var bDate = b.getNextDate()
    
    return (aDate.event_s_Date - bDate.event_s_Date)
}


AVEvent.startDatePast = function(a, b){
    var aDate = a.getPreviousDate()
    var bDate = b.getPreviousDate()
    
    return (bDate.event_s_Date - aDate.event_s_Date)
}
AVEvent.sortTourName = function(a, b){
    Log.info("AVEvent.sortTourName:" + a.eventTourName + " - " + b.eventTourName + ":" + (a.eventTourName - b.eventTourName))
    var fullA = a.eventTourName
    var fullB = b.eventTourName
    if (fullA > fullB) 
        return 1;
    if (fullA < fullB) 
        return -1;
    return 0;
}

/****************************
 Event Filters
 *****************************/
function EventFilters(){
};
EventFilters.pastAndVisible = function(item, param, index){

    return (item.isPast() && item.isVisible());
}


EventFilters.allPastAndVisible = function(item, param, index){

    return (item.isPast() && item.isVisible() && !item.isFuture());
}


EventFilters.futureAndVisible = function(item, param, index){

    return (item.isFuture() && item.isVisible());
}


EventFilters.isVisible = function(item, param, index){

    return (item.isVisible());
}


// Date class
function EventDate(){
    this._date = DateUtils.getToday()
    this._isReady = false
    this.eventId = ""
    this.dateId = ""
    this.eventTitle = ""
    this.eventThumbNailImage = ""
    this.eventDetailImage = ""
    this.eventAddress = ""
    this.eventCity = ""
    this.eventState = ""
    this.eventVenue = ""
    this.eventStartDate = ""
    this.event_s_Date
    this.eventEndDate = ""
    this.event_e_Date
    this.eventTime = ""
    this.eventAge = ""
    this.eventRsvpUrl = ""
    this.eventRsvpStartDate = ""
	this.eventRsvpStartTime = ""
    this.rsvp_s_Date
    this.eventRsvpEndDate = ""
	this.eventRsvpEndTime = ""
    this.rsvp_e_Date
    this.eventCapacity = 0
    this.eventHideRSVP = true
    this.eventHideDate = false
    this.eventInterviewLink = ""
    this.eventTrailerLink = ""
    this.eventPhotosLink = ""
    this.eventAudioLink = ""
}



EventDate.prototype.setToday = function(date){
    if (ObjectUtils.isDate(date)) {
        this._date = date;
    }
}


EventDate.prototype.isReady = function(){
    var oldestDate = new Date(0)
    if (this.event_s_Date > oldestDate && this.event_e_Date > oldestDate) {
        this._isReady = true
    }
    else {
        this._isReady = false
    }
    
    return this._isReady
}


EventDate.prototype.isPast = function(){

    return this._date > this.event_e_Date
}


EventDate.prototype.isFuture = function(){

    return this._date <= this.event_e_Date
}


EventDate.prototype.isVisible = function(){
    var v = true
    if (this.eventHideDate + 0) {
        v = false
    }
    
    return v
}


EventDate.prototype.showRSVP = function(){
    var show = false
    if (this.eventId != "" && this.eventCapacity > 0) {
        if (!this.eventHideRSVP) {
            if (this.eventRsvpUrl.length > 0) {
                if (this.rsvp_s_Date && this.rsvp_e_Date) {
                
                    if (this._date >= this.rsvp_s_Date && this._date <= this.rsvp_e_Date) {
                        show = true
                    }
                }
                else {
                    show = true
                }
            }
        }
    }
    return show
}
EventDate.prototype.showClosedRSVP = function(){
    var show = false
    if (this.eventId != "" && this.eventCapacity > 0) {
        if (!this.eventHideRSVP) {
            if (this.eventRsvpUrl.length > 0) {
                if ( this.event_e_Date&& this.rsvp_e_Date) {              
                    if (this._date >= this.rsvp_e_Date && this._date <= this.event_e_Date) {
                        show = true
                    }
                }
                else {
                    show = true
                }
            }
        }
    }
    return show
}


EventDate.prototype.showExpandImage = function(){
    var show = false;
    //Log.info("EventDate::showExpandImage ->this.eventThumbNailImage:" + this.eventThumbNailImage + " this.eventDetailImage:" + this.eventDetailImage)
    if (this.eventThumbNailImage.length > 0 && this.eventDetailImage.length > 0) {
        show = true;
    }
    
    return show;
}


EventDate.prototype._convertDates = function(){
    if (this.eventStartDate.length > 0) {
    
        this.event_s_Date = DateUtils.convertStringToDate(this.eventStartDate, "23:59")
        this.eventStartDate = this.formatDateString(this.eventStartDate, ".")
    }
    if (this.eventEndDate.length > 0) {
        this.event_e_Date = DateUtils.convertStringToDate(this.eventEndDate, "23:59")
        this.eventEndDate = this.formatDateString(this.eventEndDate, ".")
    }
	var tempDate;
    if (this.eventRsvpStartDate.length > 0) {
		tempDate = DateUtils.convertStringToDate(this.eventRsvpStartDate, this.eventRsvpStartTime)
        this.rsvp_s_Date = DateUtils.convertPDTtoLocal(tempDate)
        //this.eventRsvpStartDate = this.formatDateString(this.eventRsvpStartDate, "/")
    }
    if (this.eventRsvpEndDate.length > 0) {
		tempDate  = DateUtils.convertStringToDate(this.eventRsvpEndDate, this.eventRsvpEndTime)
        this.rsvp_e_Date = DateUtils.convertPDTtoLocal(tempDate)
        //this.eventRsvpEndDate = this.formatDateString(this.eventRsvpEndDate, "/")
    }
}
EventDate.prototype.formatDateString = function(dateString, newSeparator, oldSeparator){
    var newDataString = ""
    if (!oldSeparator) {
        oldSeparator = "/"
    }
    var dateArray = dateString.split(oldSeparator)
    if (dateArray.length > 2) {
        newDataString = dateArray[0] + newSeparator + dateArray[1] + newSeparator + dateArray[2]
    }
    return newDataString
}


EventDate.prototype.toString = function(){

    return '[EventDate name="' + this.eventTitle + '"]'
}


EventDate.prototype._getProperty = function(object, propertyString, defaultValue){
    if (object[propertyString]) {
    
        return object[propertyString]
    }
    else {
    
        return defaultValue
    }
}


EventDate.startDateFuture = function(a, b){

    return (a.event_s_Date - b.event_s_Date)
}


EventDate.startDatePast = function(a, b){

    return (b.event_s_Date - a.event_s_Date)
}


EventDate.stateAbbr = function(a, b){
    var s = new States()
    var fullA = s.getNameFromAbbr(a.eventState)
    var fullB = s.getNameFromAbbr(b.eventState)
    if (fullA > fullB) 
        return 1;
    if (fullA < fullB) 
        return -1;
    return 0;
}
function StringUtils(){
}
StringUtils.padLeft = function(strToPad, padString, numOfChars){
	var paddedString = strToPad.toString()
	if (numOfChars>0){
		while(paddedString.length <numOfChars){
			paddedString = padString + paddedString
		}
	}
	return paddedString
}

function DateUtils(){
};
// expects a string "MM/DD/YYYY" or "M/D/YYYY or M.D.YYYY"
DateUtils.convertStringToDate = function(strDate, strTime){
    var dateArray
    if (strDate.indexOf(".") > -1) {
        dateArray = strDate.split(".")
    }
    else {
        dateArray = strDate.split("/")
    }
	if (!strTime) {
		strTime = "00:00"
	}
    var timeArray =  strTime.split(":")
	var hour = parseInt(timeArray[0])
	hour = (isNaN(hour))?0:hour
	var minute = parseInt(timeArray[1])
	minute = (isNaN(minute))?0:minute
	
	
    return new Date(dateArray[2], dateArray[0] - 1, dateArray[1], hour, minute, 0, 0)
}
DateUtils.convertTeamSiteTimeTo24hour= function(timeStr){
    timeArray = timeStr.split(":");
    var hour = parseInt(timeArray[0]);
    hour = (isNaN(hour) ? 0 : hour);
    
    var min = parseInt(timeArray[1]);
    min = (isNaN(min) ? 0 : min);
    
    var amPmStr = timeArray[2];
	amPmStr = (amPmStr)?amPmStr.toLowerCase():"";
    var time24str;
    //
    if (amPmStr == "am") {
        // if midnight then set to 0
        hour = (hour >= 12) ? 0 : hour;
    }
    else if (amPmStr == "pm") {
        hour = hour + 12;
        // if noon, then set to 12
        hour = (hour >= 24) ? 12 : hour;
    }
    else {
    // already in 24 hour -> do nothing
    }
    time24str = StringUtils.padLeft(hour, "0", 2) + ":" + StringUtils.padLeft(min, "0", 2)
    return time24str;
    
}
// expects a date string "MM/DD/YYYY" or "M/D/YYYY or M.D.YYYY" and time string hh:mm
DateUtils.convertPDTtoLocal = function(date){
	var PDTOffsetInMinutes = 420
	return DateUtils.convertFromLocalToOffset(date, PDTOffsetInMinutes)
}

DateUtils.convertFromLocalToOffset=function(date, newOffsetInMins){
	var d =(!date)?new Date():date
	var newO =(!newOffsetInMins)?0:newOffsetInMins
	var currentO = date.getTimezoneOffset()
	var msInMinute = 60000
	return new Date(d.getTime() + ((newO - currentO)* msInMinute ))
}

// for comparisions create a date that is set to midnight
DateUtils.getToday = function(){
    var today = new Date()
    
   // return new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0)
	return new Date()
}


DateUtils.getYearaString = function(aDate){

    return aDate.getFullYear()
}


function ArrayUtils(){
};
ArrayUtils.filter = function(array, callback, thisObject){
    var newArray = new Array()
    if (array) {
        for (var i = 0; i < array.length; i++) {
            if (ArrayUtils.evalFilterFunction(array[i], i, array, callback, thisObject)) {
                newArray.push(array[i])
            }
        }
    }
    else {
        //Log.warn("ArrayUtils.filter->array is undefined")
    }
    
    return newArray
}


ArrayUtils.every = function(array, callback, thisObject){
    var allPass = true
    if (array) {
        for (var i = 0; i < array.length; i++) {
            if (!ArrayUtils.evalFilterFunction(array[i], i, array, callback, thisObject)) {
                allPass = false
                break;
            }
        }
    }
    else {
        //Log.warn("ArrayUtils.every->array is undefined")
        allPass = false
    }
    
    return allPass
}


ArrayUtils.some = function(array, callback, thisObject){
    var hasAny = false
    if (array) {
        for (var i = 0; i < array.length; i++) {
            if (ArrayUtils.evalFilterFunction(array[i], i, array, callback, thisObject)) {
                hasAny = true
                break;
            }
        }
    }
    else {
        //Log.warn("ArrayUtils.some ->array is undefined")
    }
    
    return hasAny
}


// evalFilterFunction accepts 3 types of functions
// function without an object
// method in object and object -> same as AS3.0
// method name as String and Object -> does not check to see if function is part of object, so
// it may fail silently
ArrayUtils.evalFilterFunction = function(element, index, array, filterFunction, thisObject){
    var isTrue = false;
    if (thisObject) {
        if (ObjectUtils.isFunction(filterFunction)) {
            if (ObjectUtils.apply(filterFunction, thisObject, element, index, array)) {
                isTrue = true;
            }
        }
        else {
            if (thisObject[filterFunction](element, index, array)) {
                isTrue = true;
            }
        }
    }
    else {
        if (filterFunction(element, index, array)) {
            isTrue = true;
        }
    }
    
    return isTrue;
}


ArrayUtils.sortNumericAsc = function(a, b){

    return a - b
}


ArrayUtils.sortNumericDsc = function(a, b){

    return b - a
}


// this function returns and array if it recieves and aray or just a single object
// JSON converts arrays of one element to an object, this converts them back to
// simplify parsing logic
ArrayUtils.getArrayFromJSONNode = function(objectOrArray){
    var newArray
    if (ObjectUtils.isArray(objectOrArray)) {
        newArray = objectOrArray
    }
    else {
        newArray = new Array()
        newArray.push(objectOrArray)
    }
    
    return newArray
}


// ObjectUtils is a collection of functions to ease object instrospection
// calling objects by reference
function ObjectUtils(){
};
ObjectUtils.is = function(obj, typeString){
    if (obj) {
    
        return !(obj.constructor.toString().indexOf(typeString) == -1);
    }
    else {
    
        return "undefined"
    }
}


ObjectUtils.isArray = function(obj){

    //return !(obj.constructor.toString().indexOf("Array") == -1);
    return ObjectUtils.is(obj, "Array")
}


ObjectUtils.isFunction = function(obj){

    return ObjectUtils.is(obj, "Function")
}


ObjectUtils.isString = function(obj){

    return ObjectUtils.is(obj, "String")
}


ObjectUtils.isDate = function(obj){

    return ObjectUtils.is(obj, "Date")
}


// applies an functionreference to an Object
ObjectUtils.apply = function(afunction, object){
    var args = new Array()
    if (arguments.length > 2) {
        for (var i = 2; i < arguments.length; i++) {
            args.push(arguments[i])
        }
    }
    
    return afunction.apply(object, args)
}


/* Firefox and IE wrapper class for console
 this class hadles IE delayed instantiation of console and adds
 additional stub methods for IE so the FireBug methods do not
 create errors
 Usage: once the page loads call setLog and pass it the console object
 for jQuery:
 $(function()
 {
 setLog(console);
 // additional tasks ...
 }
 */
function callLog(type, msg){
    Log.info(msg)
}

function setLog(consoleObject){
    Log = consoleObject;
    if (!Log["time"]) {
        Log.dir = function(object){
        };
        Log.dirxml = function(object){
        };
        Log.trace = function(object){
            Log.info("TRACE:" + object)
        };
        Log.group = function(object){
            Log.info("GROUP:" + object)
        };
        Log.groupCollapsed = function(object){
        };
        Log.groupEnd = function(object){
            Log.info("GROUPEND:" + object)
        };
        Log.time = function(name){
        };
        Log.timeEnd = function(name){
        };
        Log.profile = function(){
        };
        Log.profileEnd = function(){
        };
        Log.count = function(object){
        };
        Log.debug = function(object){
            Log.info("DEBUG:" + object)
        };
    }
}



function Log(){
}



Log.info = function(object){
};
Log.log = function(object){
};
Log.warn = function(object){
};
Log.error = function(object){
};
Log.assert = function(expression){
};
Log.dir = function(object){
};
Log.dirxml = function(object){
};
Log.trace = function(object){
};
Log.group = function(object){
};
Log.groupCollapsed = function(object){
};
Log.groupEnd = function(object){
};
Log.time = function(name){
};
Log.timeEnd = function(name){
};
Log.profile = function(){
};
Log.profileEnd = function(){
};
Log.count = function(object){
};
Log.debug = function(object){
};
