
////////////////////////////////////////////////////////////////////////////////////////////////////
// Constants
////////////////////////////////////////////////////////////////////////////////////////////////////
var PROV_COOKIE = "eventProv";
var CITY_COOKIE = "eventCity";
var DATE_COOKIE = "eventDate";
var DATE_FORMAT = "dd-mm-yyyy";
var DATE_ISO_FORMAT = "yyyy-mm-dd";
var TIME_FORMAT = "HH:mm:ss";

////////////////////////////////////////////////////////////////////////////////////////////////////
// EventsManager contructor
////////////////////////////////////////////////////////////////////////////////////////////////////
function EventsManager()
{
    var eventsManager = this;

    this.events = new Array();
    this.provinces = new Array();

    this.lang = 'en';
    this.province = 0;
    this.city = 0;
    
    this.venue = 0;
    this.artist = 0;
    this.startDate = new Date();
    this.period = 7;

    this.maxCount = 50;
    this.onLoadHandler = new EventHandler();
    this.onEventsLoadedHandler = new EventHandler();

    this.loadEvents = function()
        {
            this.onLoad();

            var http = new HttpRequestHandler(true, this.onEventsDataLoaded);
            var province = this.getSelectedProvince();
            var city = this.getSelectedCity();
            var regionPath = province.name.toLowerCase() + '/' + city.name.toLowerCase();
            var end = new Date(this.startDate.getTime() + (24*60*60*1000*(this.period)));
            var url;

            url = 'eventlist.do?'+
                'd='+this.startDate.format(DATE_FORMAT)+'&t='+this.startDate.getTime()+
                '&l='+this.lang+
                '&r='+encodeURIComponent(regionPath)+
                '&e=' + end.format(DATE_FORMAT)+
                '&c=' + this.maxCount;

            http.getText(url);
        }
   
    this.onEventsDataLoaded = function(iUrl, iContent)
        {
            var rows = iContent.split('\n');
            
            eventsManager.clearEvents();
            for (var r = 0; r < rows.length; r++)
            {
                var row = rows[r];
                var fields = row.split('|');
                
                if (fields.length <= 1)
                    continue;

                var e = new EventListItem(fields);
                if (!e.id)
                    continue;
                
                eventsManager.events[eventsManager.events.length] = e;        
            }
            
            eventsManager.onEventsLoaded();
        }

    this.addOnEventsLoaded = function(iEventHandler)
        {
            this.onEventsLoadedHandler.add(iEventHandler);
        }
        
    this.addOnLoad = function(iEventHandler)
        {
            this.onLoadHandler.add(iEventHandler)
        }

    this.update = function(iReload)
        {
            if (!iReload)
                iReload = false;
            eventsManager.onEventsLoadedHandler.invoke();
        }

    this.onEventsLoaded = function()
        {
            eventsManager.update(true);
        }

    this.onLoad = function()
        { eventsManager.onLoadHandler.invoke(); }

    this.clearEvents = function()
        { this.events = new Array(); }

    this.addProvince = function(iProvince)
        { this.provinces[this.provinces.length] = iProvince; }
    
    this.findProvince = function(iProvince)
        {
            var province = iProvince.toLowerCase();
            for(var i = 0; i < this.provinces.length; i++)
            {
                if (this.provinces[i].name.toLowerCase() == province)
                    return i;
            }
            return -1;
        }
    
    this.getSelectedProvince = function()
        { return this.provinces[this.province]; }
    
    this.getSelectedCity = function()
        { return this.getSelectedProvince().cities[this.city]; }        

    this.selectDate = function(iDate)
        {
            this.startDate = iDate;
            this.saveToCookies();
        }
        
    this.selectPeriod = function(iPeriod)
        {
            this.period = iPeriod;
        }

    this.selectRegion = function(iProvinceIndex, iCityIndex)
        {
            this.province = iProvinceIndex;
            this.city = iCityIndex;
            
            this.saveToCookies();
        }    

    this.selectRegionByName = function(iProvince, iCity)
        {
            var p = this.findProvince(iProvince);
            if (p >= 0)
            {
                var province = this.provinces[p];
                var c = province.findCity(iCity);
                
                if (c >= 0)
                {
                    this.province = p;
                    this.city = c;
                    return true;
                }
            }

            return false;
        }
 
    this.selectFromCookies = function()
        {
            var date = Cookies.get(DATE_COOKIE);
            if (date && !isUndefined(date))
                this.startDate = new Date(date);

            var province = Cookies.get(PROV_COOKIE);
            var city = Cookies.get(CITY_COOKIE);
            if (province && !isUndefined(province) && city && !isUndefined(city))
                return this.selectRegionByName(province, city);
            
            return false;
        }

    this.saveToCookies = function()
        {
            var province = Cookies.get(PROV_COOKIE);
            var city = Cookies.get(CITY_COOKIE);
            var today = new Date();
            var dateExpiry = new Date(today.getFullYear(), today.getMonth(), today.getDate(), today.getHours() + 1);
            var locationExpiry = new Date(today.getFullYear() + 1, today.getMonth(), today.getDate());
            
            Cookies.set(DATE_COOKIE, this.startDate.toGMTString(), dateExpiry);
            Cookies.set(PROV_COOKIE, this.getSelectedProvince().name, locationExpiry);
            Cookies.set(CITY_COOKIE, this.getSelectedCity().name, locationExpiry);
        }

    this.selectVenue = function(iVenueId)
        {
            this.venue = iVenueId;
        }

    this.selectArtist = function(iArtistId)
        {
            this.artist = iArtistId;
        }

    this.getEvents = function(iCount, iSortBy)
        {
            var events = new Array();

            for (var i = 0; i < this.events.length; i++)
            {
                var e = this.events[i];

                // filter by venue
                if (this.venue != 0 && this.venue != e.venueId)
                    continue;

                // filter by artist
                if (this.artist != 0 && this.artist != e.artistId)
                    continue;

                events[events.length] = e;
            }

            if (iSortBy)
                events.sort(iSortBy);

            if (iCount)
            {
                while(events.length > iCount)
                    events.pop();
            }

            return events;
        }

    this.getVenues = function()
        {
            var venuesIds = new Object();
            var venues = new Array();

            for (var i = 0; i < this.events.length; i++)
            {
                var e = this.events[i];

                if (venuesIds[e.venueId])
                    continue;

                venuesIds[e.venueId] = 1;
                venues[venues.length] = new Venue(e.venueId, e.venueName);
            }

            return venues;
        }

    this.getArtists = function()
        {
            var artistsIds = new Object();
            var artists = new Array();

            for (var i = 0; i < this.events.length; i++)
            {
                var e = this.events[i];
            
                if (artistsIds[e.artistId])
                    continue;
                
                artistsIds[e.artistId] = 1;
                artists[artists.length] = new Artist(e.artistId, e.title);
            }
            
            return artists;
        }

}


////////////////////////////////////////////////////////////////////////////////////////////////////
// EventsRegionControl
////////////////////////////////////////////////////////////////////////////////////////////////////
function EventsRegionControl(iEventsManager, iId)
{
    var eventRegionControl = this;

    this.id = iId;
    this._super = Widget;
    this._super(iId+'_control');
    
    this.menusId = this.id + '_menus';
    this.labelId = this.id + '_label';
    this.textId = this.id + '_text';
    this.formName = this.id + '_form';
    
    this.menus = new Widget(this.menusId);
    this.label = new Widget(this.labelId);
    this.text = new Widget(this.textId);
    
    this.eventsManager = iEventsManager;


    this.updateDisplayRegion = function()
        {
            var region = eventRegionControl.eventsManager.getSelectedProvince().displayName + ', ' + eventRegionControl.eventsManager.getSelectedCity().displayName;
            eventRegionControl.text.getElement().innerHTML = region;
        }

    this.updateProvinces = function()
        {
            var form = document.forms[eventRegionControl.formName];
            var provinceControl = form.province;
            var provinces = eventRegionControl.eventsManager.provinces;
            
            provinceControl.options.length = 0;
            for (var i = 0; i < provinces.length; i++)
                provinceControl.options[provinceControl.options.length] = new Option(provinces[i].displayName, i);
            provinceControl.selectedIndex = eventRegionControl.eventsManager.province;
        }
        
    this.updateCities = function()
        {
            var form = document.forms[eventRegionControl.formName];
            var cityControl = form.city;
            var cities = eventRegionControl.eventsManager.getSelectedProvince().cities;
            
            cityControl.options.length = 0;
            if (cities.length > 0)
            {
                for (var i = 0; i < cities.length; i++)
                    cityControl.options[cityControl.options.length] = new Option(cities[i].displayName, i);
                cityControl.selectedIndex = eventRegionControl.eventsManager.city;
            }
        }

    this.update = function()
        {
            eventRegionControl.updateDisplayRegion();
            eventRegionControl.updateProvinces();
            eventRegionControl.updateCities();
        }

    this.onChangeRegionClick = function()
        {
            eventRegionControl.menus.show();
            eventRegionControl.label.hide();
        }

    this.onProvinceSelected = function()
        {
            var form = document.forms[eventRegionControl.formName];
            var provinceControl = form.province;
            eventRegionControl.eventsManager.selectRegion(provinceControl.value, 0);
            eventRegionControl.updateCities();
        }

    this.onSubmit = function()
        {
            var form = document.forms[eventRegionControl.formName];
            var provinceControl = form.province;
            var cityControl = form.city;

            eventRegionControl.eventsManager.selectRegion(provinceControl.value, cityControl.value);
            
            eventRegionControl.updateDisplayRegion();
            eventRegionControl.menus.hide();
            eventRegionControl.label.show();            
            
            eventRegionControl.eventsManager.loadEvents();
        }
        

    this.eventsManager.addOnEventsLoaded(this.update);
    this.update();
    
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// VenueControl
////////////////////////////////////////////////////////////////////////////////////////////////////
function VenueControl(iEventsManager, iId)
{
    var venueControl = this;

    this.id = iId;
    this._super = Widget;    
    this._super(this.id + '_control');
    
    this.formName = this.id + '_form';
    
    this.eventsManager = iEventsManager;


    this.update = function()
        {
            var form = document.forms[venueControl.formName];
            var select = form.venue;
            var venues = venueControl.eventsManager.getVenues();

            select.options.length = 0;
            select.options[select.options.length] = new Option(Language.getEntry('allvenues'), 0);

            for (var i = 0; i < venues.length; i++)
            {
                select.options[select.options.length] = new Option(venues[i].name, venues[i].id);
                if (venueControl.eventsManager.venue == venues[i].id)
                    select.options.selectedIndex = i+1;
            }
        }

    this.onVenueSelected = function()
        {
            var form = document.forms[venueControl.formName];
            var select = form.venue;        
        
            venueControl.eventsManager.selectVenue(select.options[select.options.selectedIndex].value);
            venueControl.eventsManager.update();
        }
        

    this.eventsManager.addOnEventsLoaded(this.update);
    this.update();

}


////////////////////////////////////////////////////////////////////////////////////////////////////
// ArtistControl
////////////////////////////////////////////////////////////////////////////////////////////////////
function ArtistControl(iEventsManager, iId)
{
    var artistControl = this;

    this.id = iId;
    this._super = Widget;    
    this._super(this.id + '_control');
    
    this.formName = this.id + '_form';
    
    this.eventsManager = iEventsManager;

    this.update = function()
        {
            var form = document.forms[artistControl.formName];
            var select = form.artist;
            var artists = artistControl.eventsManager.getArtists();

            select.options.length = 0;
            select.options[select.options.length] = new Option(Language.getEntry('allartists'), 0);

            for (var i = 0; i < artists.length; i++)
            {
                select.options[select.options.length] = new Option(artists[i].name, artists[i].id);
                if (artistControl.eventsManager.artist == artists[i].id)
                    select.options.selectedIndex = i+1;
            }
        }

    this.onArtistSelected = function()
        {
            var form = document.forms[artistControl.formName];
            var select = form.artist;        
        
            artistControl.eventsManager.selectArtist(select.options[select.options.selectedIndex].value);
            artistControl.eventsManager.update();
        }
        

    this.eventsManager.addOnEventsLoaded(this.update);
    this.update();

}


////////////////////////////////////////////////////////////////////////////////////////////////////
// CalendarControl
////////////////////////////////////////////////////////////////////////////////////////////////////
function CalendarControl(iEventsManager, iId, iDate)
{
    var calendarControl = this;

    this.id = iId;
    this._super = Widget;
    this._super(this.id + '_control');
    
    this.calendarId = this.id + '_calendar';
    
    this.calendar = new Widget(this.calendarId);

    this.eventsManager = iEventsManager;

    this.update = function()
        {
            calendarControl.calendarController.setDate(new Date(calendarControl.eventsManager.startDate));
        }

    function onCalendarChange(iCalendarController)
    {
        calendarControl.eventsManager.selectDate(iCalendarController.date);
        calendarControl.eventsManager.loadEvents();
    }

    this.calendarController = Calendar.setup(
        { flat : this.calendarId, flatCallback : onCalendarChange, weekNumbers : false }
    );
    if (iDate)
        this.calendarController.setDate(iDate);
    
    this.eventsManager.addOnEventsLoaded(this.update);
    
}


////////////////////////////////////////////////////////////////////////////////////////////////////
// EventListControl
////////////////////////////////////////////////////////////////////////////////////////////////////
function EventListControl(iEventsManager, iId)
{
    var eventList = this;

    this.id = iId;
    this._super = Widget;
    this._super(this.id + '_control');
    
    this.loadingId = this.id + '_loading';
    this.tableId = this.id + '_table';
    this.messageId = this.id + '_message';
    this.noEventsId = this.id + '_noevents';
    
    this.loading = new Widget(this.loadingId);
    this.table = new Widget(this.tableId);
    this.message = new Widget(this.messageId);
    this.noEvents = new Widget(this.noEventsId);    
    
    this.eventsManager = iEventsManager;
    this.rowCount = 12;
    this.sortColumn = 2;
    this.sortDirection = 1;
    this.columns = new Array('title', 'venueName', 'date');
    this.rowClasses = null;
    

    this.showLoading = function()
        {
            eventList.table.hide();
            eventList.noEvents.hide();
            eventList.message.hide();
            eventList.loading.show();
        }

    this.clearTable = function()
        {
            var table = eventList.table.getElement();
            
            while(table.rows.length > 1)
                table.deleteRow(1);
        }

    this.sortBy = function(iColumn)
        {
            if (this.sortColumn == iColumn)
                this.sortDirection = -this.sortDirection;
            else
            {
                this.sortColumn = iColumn;
                this.sortDirection = 1;
            }
            this.update();
        }

    this.update = function()
        {
            var events = eventList.eventsManager.getEvents(eventList.rowCount, eventList.getComparator(eventList.sortColumn, eventList.sortDirection));
            var table = eventList.table.getElement();
            
            eventList.loading.hide();
            eventList.clearTable();

            if (events.length)
            {
                var targetDate = eventList.eventsManager.startDate.format(DATE_ISO_FORMAT);		

                eventList.noEvents.hide();
                eventList.updateMessage(eventList.eventsManager.events.length+' '+Language.getEntry('eventsfound'));
                eventList.message.show();

                for (var i = 0; i < events.length && i < eventList.rowCount; i++)
                {
                    var e = events[i];
                    var row = table.insertRow(-1);
                    var bold = false;
                    var cell;

                    if (eventList.rowClasses)
                        row.className = eventList.rowClasses[i % 2];
                    
                    bold = (e.date.substr(0, 10) == targetDate);

                    cell = row.insertCell(-1);
                    cell.innerHTML = e.title;
                    if (bold)
                        cell.style.fontWeight = 'bold';
                    cell = row.insertCell(-1);
                    cell.innerHTML = e.location;
                   
                    cell = row.insertCell(-1);
                    cell.innerHTML = e.dayShort;
                                    
                    cell = row.insertCell(-1);
                    cell.innerHTML = e.hour;
                            
                }
                
                eventList.table.show();
            }
            else
            {
                eventList.updateMessage('');
                eventList.message.hide();
                eventList.noEvents.show();
            }
        }

    this.updateMessage = function(iMessage)
        {
            eventList.message.getElement().innerHTML = iMessage;        
        }

    this.getComparator = function(iColumn, iDirection)
        {
            return function(iItem1, iItem2)
                {
                    return iItem1.compare(iItem2, eventList.columns[iColumn], iDirection);
                };
        }

    this.eventsManager.addOnEventsLoaded(this.update);
    this.eventsManager.addOnLoad(this.showLoading);
    this.showLoading();
    
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// EventSummaryControl
////////////////////////////////////////////////////////////////////////////////////////////////////
function EventSummaryControl(iEventsManager, iId)
{
    var eventsSummaryControl = this;

    this.id = iId;
    this._super = Widget;
    this._super(this.id + '_control');
    
    this.loadingId = this.id + '_loading';
    this.noEventsId = this.id + '_noevents';
    this.dateId = this.id + '_date';
    this.listId = this.id + '_list';
    this.column1Id = this.id + '_col1';
    this.column2Id = this.id + '_col2';

    this.loading = new Widget(this.loadingId);
    this.noEvents = new Widget(this.noEventsId);
    this.date = new Widget(this.dateId);
    this.list = new Widget(this.listId);
    this.column1 = new Widget(this.column1Id);
    this.column2 = new Widget(this.column2Id);
    
    this.eventsManager = iEventsManager;
    this.rowCount = 3;
    
    
    this.showLoading = function()
        {
            eventsSummaryControl.list.hide();
            eventsSummaryControl.noEvents.hide();
            eventsSummaryControl.loading.show();
        }
    
    this.update = function()
        {
            var events = eventsSummaryControl.eventsManager.getEvents();
            var content;
            
            // hide loading
            eventsSummaryControl.loading.hide();
            
            // update date
            eventsSummaryControl.date.getElement().innerHTML = eventsSummaryControl.eventsManager.startDate.format(Language.getEntry('DATEFORMAT'));

            if (events.length)
            {
                // load column1
                content = '';
                for (var i = 0; i < events.length && i < eventsSummaryControl.rowCount; i++)
                    content += '<li>'+'<h5>'+events[i].titleTruncated+'</h5>'+events[i].location+'</li>';
                eventsSummaryControl.column1.getElement().innerHTML = content;
                
                // load column2
                content = '';
                for (var i = eventsSummaryControl.rowCount; i < events.length && i < eventsSummaryControl.rowCount * 2; i++)
                    content += '<li>'+'<h5>'+events[i].titleTruncated+'</h5>'+events[i].location+'</li>';
                eventsSummaryControl.column2.getElement().innerHTML = content;
                
                // show list
                eventsSummaryControl.list.show();
            }
            else
                eventsSummaryControl.noEvents.show();
        }

    this.eventsManager.addOnEventsLoaded(this.update);
    this.eventsManager.addOnLoad(this.showLoading);
    this.showLoading();
            
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// EventListItem
////////////////////////////////////////////////////////////////////////////////////////////////////
function EventListItem(iFields)
{
    var eventListItem = this;

    var r = 0;
    this.id = iFields[r++];
    this.titleTruncated = iFields[r++];
    this.titleOriginal = iFields[r++];
    this.title = iFields[r++];
    this.venueId = iFields[r++];
    this.venueName = iFields[r++];
    this.location = iFields[r++];
    this.date = iFields[r++];
    this.dayShort = iFields[r++];
    
    var h = iFields[r++].trim();
    this.hour = (h != "0:00") ? h : Language.getEntry("tocome");
    
    this.artistId = this.title.toLowerCase().replace(/^\s*|\s*$/g,'');

    this.compare = function(iItem, iField, iDirection)
        {
            var v1 = eventListItem[iField];
            var v2 = iItem[iField];
            var r = iDirection ? iDirection : 1;
        
            if (v1 < v2)
                return -r;
            else if (v1 > v2)
                return r;
            else
                return 0;            
        }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Artist
////////////////////////////////////////////////////////////////////////////////////////////////////
function Artist(iId, iName)
{
    this.id = iId;
    this.name = iName;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Venue
////////////////////////////////////////////////////////////////////////////////////////////////////
function Venue(iId, iName)
{
    this.id = iId;
    this.name = iName;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Province
////////////////////////////////////////////////////////////////////////////////////////////////////
function Province(iName)
{
    this.name = iName;
    this.displayName = Language.getEntry(iName);
    this.cities = new Array();
    
    this.addCity = function(iCity)
        {
            this.cities[this.cities.length] = iCity;
        }
        
    this.findCity = function(iCityName)
        {
            var cityName = iCityName.toLowerCase();
            for(var i = 0; i < this.cities.length; i++)
            {
                if (this.cities[i].name.toLowerCase() == cityName)
                    return i;
            }
            return -1;        
        }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// City
////////////////////////////////////////////////////////////////////////////////////////////////////
function City(iName)
{
    this.name = iName;
    this.displayName = Language.getEntry(iName);
}