godo.calendar = {
    nodes: {},
    template: "",
    state: {
        currentMonth: null,
        selectedDate: null
    },
    init: function(calendarnode, sessionsnode, navnode, bodynode, promptnode) {

        var self = this;

        self.nodes.prompt = promptnode ? $(promptnode) : $("#godoProductPrompt");
        self.nodes.calendar = calendarnode ? $(calendarnode) : $("#godoCalendar");
        self.nodes.sessions = sessionsnode ? $(sessionsnode) : $("#godoCalendar .sessions");
        self.nodes.nav = navnode ? $(navnode) : $("#godoCalendar .nav");
        self.nodes.body = bodynode ? $(bodynode) : $("#godoCalendar .calendar .body");

        // Book buttons
        self.nodes.calendar.delegate(".bookbutton", "click", function(event) {
            event.preventDefault();

            var date = $(this).attr("date");
            var sessionid = $(this).attr("sessionid");

            var theSession = null;
            $.each(availableDays[date].sessions, function(index, session) {
                if (session.sessionid == sessionid) {
                    theSession = session;
                    return false;
                }
            });
            if (productDetailData.isgiftvoucher) {
                subtotalamount = 1; // To prevent the zero check
                godo.addtocart.openvoucher(theSession);
            } else {
                godo.addtocart.open(theSession);
            }
            return false;
        });

        // Prev, next and month buttons
        self.nodes.calendar.delegate(".calendar-next, .calendar-prev, .months a, .helptext a", "click", function(event) {
            event.preventDefault();
            if (!$(this).is(".disabled")){
                var dateStr = $(this).attr("date");
                var newdate = godo.util.stringToDate(dateStr);

                self.hideSessions();
                self.loadMonth(newdate);
                return false;
            }
        });

        // Dates
        self.nodes.calendar.delegate(".dates-table a", "click", function(event) {
            event.preventDefault();

            if (self.state.selectedDate) {
                self.state.selectedDate.removeClass("selected");
            }
            var td = $(this).parent();
            self.state.selectedDate = td;
            self.state.selectedDate.addClass("selected");
            $(this).append('<span class="highlight"></span>');

            var selectedDateStr = $(this).parent().attr("date");
            var selectedDate = godo.util.stringToDate(selectedDateStr);

            var sessions = { hasBookNowBtn : false };
            if ($(this).parent().is(".avail")) {
                var selectedDay = availableDays[selectedDateStr];
                sessions = {
                    days: [{
                        date: selectedDay.date,
                        sessions: selectedDay.sessions
                    }]
                }
            } else {
                sessions.helptext = "<strong>" + selectedDate.format("dddd, d mmmm") + "</strong><br> No sessions available. <br>Try selecting a marked date."
            }

            self.loadSessions(sessions);
            return false;
        });

        // Book Now button
        self.nodes.calendar.delegate(".booknowbutton", "click", function(event) {
            event.preventDefault();

            var sessions = { hasBookNowBtn : true,
                             helptext : "Please select a marked date from the calendar above"};
            self.loadSessions(sessions);
            return false;
        });
    },


    // Change Month
    loadMonth: function(newdate) {
        var self = this;

        // Use today's date if no date is provided
        newdate = newdate ? newdate : new Date();

        self.state.currentMonth = newdate;
        if (productDetailData.isgiftvoucher) {
        	self.nodes.nav.html('<div class="head nodates"><h2>Denominations</h2></div>')
        } else if (productDetailData.hasavailability) {
        	self.loadNav(newdate);
        } else {
            self.nodes.nav.html('<div class="head nodates"><h2>Tickets</h2></div>')
        }
        self.getData(newdate);
        return false;
    },


    // Loads the full month calendar
    loadCalendar: function(days) {
        var self = this;
        // Pass the model to the view and render using mustache template
        godo.util.template.make("productCalendar", calendarDays, function(html){
            self.nodes.body.html(html);
        });
        var sessions = { hasBookNowBtn : true };
        self.loadSessions(sessions);
        return false;
    },


    // Removes the calendar
    hideCalendar: function() {
        var self = this;
        self.nodes.body.html("");
        return false;
    },


    // Displays the first prompt
    loadPrompt: function(promptinfo) {
        var self = this;
        var prompt = {
            minpricetickettype : productDetailData.minpricetickettype,
            minprice : productDetailData.minprice,
            promptinfo : promptinfo
        }
        godo.util.template.make("productDetailPrompt", prompt, function(html) {
            self.nodes.prompt.html(html);
        });
    },

    // Displays sessions in the list format and adds event for each book button
    loadSessions: function(sessions) {
        var self = this;
        sessions.hashelptext = (sessions.helptext != undefined && sessions.helptext != "");
        godo.util.template.make("productSessions", sessions, function(html){
            self.nodes.sessions.html(html);
        });
        return false;
    },


    // Removes the sessions
    hideSessions: function() {
        var self = this;
        self.nodes.sessions.html("");
        return false;
    },

    // Displays sessions in the list format and adds event for each book button
    loadVoucherPrices: function(availabledays) {
        var self = this;
        godo.util.template.make("voucherPrices", availabledays, function(html){
            self.nodes.sessions.html(html);
        });
        return false;
    },


    // Loads the month navigation and header
    loadNav: function(newdate) {
        var startDate = new Date();
        var today = new Date();
        startDate.setTime(newdate.valueOf());
        var self = this;
		var nav = {
		   months: [],
		   currentmonth: startDate.format("mmmm yyyy")
		}

		// Next button
		if (startDate.getMonth() < (today.getMonth() + 5)) {
            var nextdate = new Date();
            nextdate.setTime(startDate.valueOf());
            nextdate.setMonth(nextdate.getMonth() + 1);
            nav.next = godo.util.dateToString(nextdate);
        }

		// Prev button
		if (startDate.getMonth() > today.getMonth()) {
            var prevdate = new Date();
            prevdate.setTime(startDate.valueOf());
            prevdate.setMonth(prevdate.getMonth() - 1);
            nav.prev = godo.util.dateToString(prevdate);
		}

        for (i = 0; i < 6; i++) {
            var newMonth = {
                name: today.format("mmm"),
                date: godo.util.dateToString(today)
            }
            if (today.getMonth() === startDate.getMonth()) {
                newMonth.monthclass = "selected"
            }
            nav.months.push(newMonth);
            today.setMonth(today.getMonth() + 1);
        }

		// Pass the model to the view and render using mustache template
	    godo.util.template.make("productCalendarNav", nav, function(html){
	        self.nodes.nav.html(html);
	    });
        return false;
    },


    // Get the data from the JSON service and transform into something we can work with
    getData: function(date) {
        var self = this;

    	$.ajax({
            url: productTicketsJSONUrl,
            data: ({
            		//licence		: "8A3A894C-D6E4-401E-8E6F-57A93C6EE7D7",
            		siteUrl		: params.siteUrl,
            		productId	: params.productID,
            		date		: godo.util.dateToString(date),
            		period		: 'm',
            		interval	: '1'
            }),
            //crossDomain: true,
            //jsonpCallback: "ticketsCallback",
            dataType: "json",
            success: function(data){


                // Put the available days into a structured object ready for the front-end
                availableDays = {
                    days: []
                };
                var dateIndex = 0;
                var sessionCount = 0;
                var sessionIndex = {};
                var days = [];
                $.each(data.DATES, function(i, prodDate){
                    var dateStr = prodDate.DATE;
                    var sessionid = prodDate.SESSIONID;
                    var hasdates = true
                    var extraChargeAmount = '';
                	var extraChargeTitle = '';
                	var insuranceMinPrice = '';
                 	var insuranceRate = '';
                 	var insuranceSessionId = 0;
                	var extraChargeDescription = '';
                    if (!productDetailData.hasavailability) {
                    	hasdates = false
                    }
                	if (productDetailData.hasextracharges && productDetailData.extracharges){
                     	extraChargeAmount = productDetailData.extracharges.AMOUNT;
                     	extraChargeTitle = productDetailData.extracharges.TITLE;
                     	extraChargeDescription = productDetailData.extracharges.DESCRIPTION;
                	}
                	if (productDetailData.hasinsurance && productDetailData.insurance){
                     	insuranceMinPrice = productDetailData.insurance.MINPRICE;
                     	insuranceRate = productDetailData.insurance.RATE;
                     	insuranceSessionId = productDetailData.insurance.SESSIONID;
                	}
                    // Add date if not already in the calendar
                    if (!availableDays[dateStr]) {
                        availableDays[dateStr] = {
                            date: godo.util.stringToDate(dateStr).format("dddd, d mmmm"),
                            hasdates: hasdates,
                            sessions: []
                        }
                        days.push(dateStr);
                        dateIndex++;
                    }
                    var theDate = availableDays[dateStr];

                    // Add session if not already in the date
                    if (!sessionIndex[dateStr + "-" + sessionid]) {
                    	var thumbImage = '';
                        if (productDetailData.images.length > 0) {
                            thumbImage = productDetailData.images[0].srcthumb;
                    	}
                        sessionIndex[dateStr + "-" + sessionid] = {
                            product: productDetailData.name,
                            productid: productDetailData.id,
                            productsefname:  productDetailData.friendlyurl,
                            //formaction: "https://" + params.siteHttpsURL + "/activity/" + productDetailData.PRODUCTCODE, //order/shoppingcart.cfm",
                            formaction: cartDetailUrl,
                            //voucherPersonaliseAction: "https://" +  params.siteHttpsURL + "/gift-vouchers/" + productDetailData.friendlyurl + "/personalise",
                            voucherPersonaliseAction: "/gift-vouchers/" + productDetailData.friendlyurl + "/personalise",
                            vouchertheme: productDetailData.friendlyurl,
                            vouchervalue: prodDate.TICKETPRICE,
                            //voucherPersonaliseAction: cartDetailUrl,
                            thumbnail: thumbImage,
                            sessionname: prodDate.SESSION,
                            starttime: prodDate.STARTTIME,
                            date: godo.util.stringToDate(dateStr).format("dddd, d mmmm"),
                            datestr: dateStr,
                            sessionid: prodDate.SESSIONID,
                            onspecial: prodDate.ONSPECIAL,
                			totalplaces: prodDate.PLACESTOTAL,
                			availableplaces: prodDate.PLACESAVAILABLE,
                			hasinsurance: productDetailData.hasinsurance,
                			hasextracharges : productDetailData.hasextracharges,
                			extracharge : extraChargeAmount,
                        	extrachargetitle : extraChargeTitle,
                        	extrachargedescription : extraChargeDescription,
                        	insuranceminprice : insuranceMinPrice,
                        	insurancerate : insuranceRate,
                        	insurancesessionid : insuranceSessionId,
                            tickets: []
                        }

                        sessionCount++;
                        theDate.sessions.push(sessionIndex[dateStr + "-" + sessionid]);
                    }

                    var theSession = theDate.sessions[theDate.sessions.length - 1];

                    // Add the ticket to the session
                    var ticket = {
                        options: [],
                		label: prodDate.TICKET,
                		price: prodDate.TICKETPRICE,
                	    tickettypeid: prodDate.TICKETTYPEID,
                	    insurancesessionid: insuranceSessionId
                    }
                    for (j = 0; j <= parseInt(theSession.availableplaces); j++) {
                        var label = "";
                        var q = j * prodDate.TICKETVALIDFOR;
                        switch (prodDate.TICKETUNITSINGULAR.toLowerCase()) {
                            case "person":
                                    switch (ticket.label.toLowerCase()) {
                                         case "family package":
                                            // NOTE. Ticket Valid For does not apply in this case (hint: using j not q)
                                            if (j === 1) {
                                                label = "1 family";
                                            } else {
                                                label = j + " families";
                                            }
                                            break;
                                        case "children":
                                            if (q === 1) {
                                                label = "1 child";
                                            } else {
                                                label = q + " children";
                                            }
                                            break;
                                        case "adults":
                                            label = "adult";
                                            label = godo.util.pluralise(q, label);
                                            break;
                                        case "students":
                                            label = "student";
                                            label = godo.util.pluralise(q, label);
                                            break;
                                        default:
                                            label = q + " " + ticket.label;
                                            break;
                                    }
                                break;

                            default:
                                // Handles all non Person tickets eg. hire a Boat, Car etc
                                if (j === 1) {
                                    label = q + " " + prodDate.TICKETUNITSINGULAR;
                                } else {
                                    label = q + " " + prodDate.TICKETUNITMULTIPLE;
                                }
                                break;


                        }
                        var complexValue = sessionid.toString() + '_' + godo.util.stringToDate(dateStr).format("yyyy-mm-dd") + '_' + prodDate.TICKETTYPEID.toString() + '_' + j + '_0';
                        //var complexValue =
                        var newOption = {
                            label: label,
                            value: complexValue,
                            quantityprice: j*parseFloat(prodDate.TICKETPRICE)

                        }
                        ticket.options.push(newOption);
                    }
                    theSession.tickets.push(ticket);
                });

                for (i = 0; i < days.length; i++){
                   availableDays.days.push(availableDays[days[i]]);
                }


                calendarDays = {
                   rows: []
                };
                var firstDate = new Date(data.FIRSTDATE);
                var tempDate = new Date(firstDate.getFullYear(), firstDate.getMonth(), 1);
                var month = tempDate.getMonth();

                // Pad with days from previous month if required
                var row = 0;
                var index = 0;
                var firstDay = tempDate.getDay();
                if (firstDay === 0) {
                    firstDay = 7;
                }
                if (firstDay !== 1) {
                    var padDays = firstDay - 1;
                    calendarDays.rows[row] = {
                        days: []
                    };
                    for (i = 0; i < padDays; i++) {
                        var outerDay = {
                            tdclass: "outer"
                        }
                        calendarDays.rows[row].days.push(outerDay);
                        index++;
                    }
                }

                // Loop through each day of the month and build date object
                while (tempDate.getMonth() == month) {
                    var day = {
                        value: tempDate.getDate(),
                        tdclass: ""
                    };
                    if (tempDate.getDay() === 0 || tempDate.getDay() === 6) {
                        day.tdclass += " weekend";
                    }
                    var tempDateStr = godo.util.dateToString(tempDate);
                    day.date = tempDateStr;
                    if (availableDays[tempDateStr]) {
                        day.tdclass += " avail";
                        day.href = "#";
                    }

                    if (index % 7 === 0 && index !== 0) {
                        row++;
                    }

                    if (!calendarDays.rows[row]) {
                        calendarDays.rows[row] = {
                            days: []
                        };
                    }
                    calendarDays.rows[row].days.push(day);
                    tempDate.setDate(tempDate.getDate() + 1);
                    index++;
                }

                // Pad with days from next month if required
                if (index % 7 !== 0) {
                    while (index % 7 !== 0) {
                        var outerDay = {
                            tdclass: "outer"
                        }
                        calendarDays.rows[row].days.push(outerDay);
                        index++;
                    }
                }

                // If there are less than 5 sessions available in the month use the list view
                if (sessionCount > 0) {
                	if (productDetailData.isgiftvoucher) {
                		self.loadVoucherPrices(availableDays);
                	} else if (sessionCount > 5 && productDetailData.hasavailability) {
                        self.loadPrompt("SELECT DATE")
                        self.loadCalendar(calendarDays);
                    } else {
                        if (productDetailData.isTickets) {
                            self.loadPrompt("SELECT TICKETS")
                        } else {
                            self.loadPrompt("SELECT SESSION")
                        }
                        self.loadSessions(availableDays);
                        self.hideCalendar();
                    }
                } else {
                    var helptext = "";
                    if (productDetailData.firstavailabledate) {
                        var date = new Date(productDetailData.firstavailabledate);
                        helptext = 'The first available session is on <strong><a href="?date=' + godo.util.dateToString(date) + '" date="' + godo.util.dateToString(date) + '">' + date.format("dddd, d mmmm") + '</a></strong>';
                    } else {
                        helptext = 'Sorry, there are no sessions available for this activity.'
                    }

                    self.hideCalendar();
                    self.loadSessions({
                        helptext: helptext
                    });
                }
            }
    	});
        return false;
    }
}
