

function Calendar( leftCalendar, rightCalendar) {
    var logger = LogFactory.getLog("Calendar.js");

    var self = this;

    var months = new Array("Jan", "Feb", "Mar", "Apr", "May", "Jun",
                           "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");

    // HTML ID values for the left and right calendar elements
    this.leftCal = leftCalendar;
    this.rightCal = rightCalendar;

    // The javascript reservation object
    var reservation;
    this.setReservation = function(r) {
        reservation = r;
    }

    var calendarDateRegex = new RegExp("^\\d{6}$");
    var calTableRegex     = new RegExp("^\\d{4}$");

    var tempMessage = "<div class='calTempMessage'>Loading availability ....</div>";
    var MAX_DAYS_BETWEEN_START_END = 20;

    var calIdLoaded = new Array();
    calIdLoaded[this.leftCal] = false;
    calIdLoaded[this.rightCal] = false;

    var calIdDate = new Array();
    var today = new Date();

    var jumpToDiv;
    var calLeft;
    var calRight;

    this.init = function() {

        var clearDates = document.getElementById("clearDates");
        clearDates.onclick = function() {
            reservation.clearDates();
            //reservation.setStartDate("");
            self.updateCalendars();
            return false;
        }

        jumpToDiv = document.getElementById( "jumpToMonth" );
        calLeft     = document.getElementById( "calLeft" );
        calRight     = document.getElementById( "calRight" );

        // Set mouseovers
        var links = jumpToDiv.getElementsByTagName("a");
        for( var i=0; i<links.length; i++ ) {
            links[i].onmouseover =function(e) {
                var elem = getEventSource(e);
                var msg;
                if( elem.innerText ) {
                    msg = "Jump To: " + elem.innerText;
                } else {
                    msg = "Jump To: " + elem.text;
                }

                window.status = msg;
                return true;
            };
            links[i].onmouseout = function() {
                window.status = "";
                return true;
            };

        }

    }

    this.loadCalendars = function() {
//       try{

        if( arguments[0] && !( calIdLoaded[self.leftCal] && calIdLoaded[self.rightCal] ) ) {
            // Skip this if there is an argument and both cals aren't loaded
            return;
        }

		var leapCal;

		try{
			leapCal = document.getElementById("frmLeapCal").value;
		}catch(ie){}

        if( calIdLoaded[self.leftCal] ) {
            // load with the existing date on the left
            var cal1      = document.getElementById( self.leftCal );
            var tableId;
            var tNodes = cal1.getElementsByTagName("table");
            for( var i=0; i<tNodes.length; i++ ) {
                tableId = tNodes[i].id;
            }

            if( !tableId.substr ){
               return;
               }

            var leftDate = tableId.substr( 8, 4 );
            if( ! calTableRegex.test( leftDate ) ) {
                return;
            }

            self.loadCalsFromString( leftDate );
		} else if( leapCal ){
			self.loadCalsFromString( leapCal );
        } else if( res.getStartDate().length == 0 ) {
            // Today's month goes on the left
            var firstCal = "" + today.getFullYear() + getMonthAsString(today);
            firstCal = firstCal.substr(2, 6);
            var lastCal = getNextMonthString( today );
            self.getCalendar( this.leftCal,  firstCal );
            self.getCalendar( this.rightCal, lastCal );

        } else {
            self.loadCalsFromString( res.getStartDate().substr(0, 4) );

        }
//       }catch( e ){
//          return;
//       }

    }

    this.loadCalsFromString = function( dateStr ) {

        var startMonth = dateStr.substr(2, 2) -1;
        firstCal = dateStr;
        var check = startMonth - today.getMonth();
        if(  check != -2 && check != 10 ) {
            if( startMonth == 11 ) {
                var rightDate = dateStr.substring(0, 2);
                rightDate *= 1;
                rightDate++;
                rightDate = "" + rightDate;
                if( rightDate.length == 1 ) rightDate = "0" + rightDate;
                lastCal = rightDate + "01";
            } else {
                lastCal = dateStr.substring(0, 2) +
                    (((startMonth+2) < 10) ? "0" : "") + (startMonth+2 );
            }

        } else {
            lastCal = firstCal;
            if( startMonth == 0 ) {
                firstCal = (dateStr.substring(0, 2)-1) + "12";
            } else {
                firstCal = dateStr.substring(0, 2) +
                    (((startMonth) < 10) ? "0" : "") + (startMonth);
            }

        }

        self.getCalendar( self.leftCal,  firstCal );
        self.getCalendar( self.rightCal, lastCal );

    }

    function getMonthAsString( date ) {
        var mon = date.getMonth() + 1;
        return (( mon < 10 ) ?  "0" + mon : mon );
    }

    // onclick handler to load calendars based on a date
    var loadCalendarsForDate = function(e) {
        var elem = getEventSource(e);
        if( elem.id.length > 0 && elem.id.indexOf("jmpto") == 0 ) {
			try{
				document.getElementById("frmLeapCal").value = elem.id.substr(5,4);
			}catch(ie){}
            self.loadCalsFromString( elem.id.substr(5, 4) );
        }
        return false;
    }

    this.getCalendar = function( calId, date ) {
        logger.debug("Enter getCalendar(), calId=", calId, ", date=", date);

        if( !calTableRegex.test( date ) ){
           return;
           }

        disableLeftRight();
        var calElem     = document.getElementById( calId );
        calElem.innerHTML = tempMessage; // is this necessary?
        calIdLoaded[calId] = false;

        var year = "20" + date.substr(0, 2);
        var month = date.substr(2, 4);

        var http = getHTTPObject();
        var cursorHelper = new CursorHelper();
        cursorHelper.setNewCursor("wait");
        // Should this be a POST?
        var uri = "/reservation/GetCalendar.do?" +
                  reservation.getFormPostData() +
                  "&calDate=" + date;
        http.open("GET", uri );
        http.onreadystatechange =
            function() {
                if (http.readyState == 4 ) {
                    if( http.status == 200 ) {
                        logger.debug("in handleHttpResponse() - setting innerHTML");
                        calElem.innerHTML = http.responseText;
                        calIdLoaded[calId] = true;
                        calElem.onclick = selectDate; // do this here?
                        self.updateCalendar( calId );
                        calIdDate[calId] = new Date( year, month - 1, 1 );
                        enableLeftRight();
                    } else {
                        logger.warn("Problem with response, code = ", http.status, "\n",
                                           http.responseText);
                    }
                    cursorHelper.removeCursor();
                }
            }

        http.send( null );


        logger.debug("Exit getCalendar()");
    }

    this.updateCalendar = function( calId ) {
        logger.debug("Enter updateCalendar(), calId=", calId);

        var calElem     = document.getElementById( calId );
        calElem.onclick = selectDate;

        var nodes = calElem.getElementsByTagName("A");
        for( var i=0; i<nodes.length; i++ ) {

            var nodei = nodes[i];
            var subNode = nodei.lastChild;
            if( subNode.nodeType == 1 ) {
                nodei.removeChild( subNode );
            }

            if( reservation.getStartDate().length == 0 ||
                reservation.getStartDate() > nodei.id ) {

                removeSelClass( nodei );

            } else if( reservation.getStartDate() == nodei.id ) {

                if( reservation.isValid() ) {
                    addAmount( nodei, reservation.getAmount(nodei.id) );
                    addSelClass( nodei );
                } else {
                    addSelClass( nodei );
                }

            } else if( reservation.getEndDate().length == 0 ||
                       reservation.getEndDate() < nodei.id ) {

                removeSelClass( nodei );

            } else {

                if( reservation.isValid() ) {
                    addAmount( nodei, reservation.getAmount(nodei.id) );
                    addSelClass( nodei );
                } else {
                    addSelClass( nodei );
                }

            }

        }

        logger.debug("Exit updateCalendar(), calId=", calId);
    }

    function removeSelClass( node ) {
        var className = node.className;
        if( className.indexOf(" sel") > 0 ) {
            node.className = className.substring( 0, className.indexOf(" sel") );
        }
    }

    function addSelClass( node ) {
        if( node.className.indexOf(" sel") < 0 ) {
            node.className = node.className + " sel";
        }
    }

    var tmpNode = document.createElement("SPAN");
    function addAmount( node, amount ) {
        var newNode = tmpNode.cloneNode(false);
        var newTxt  = document.createTextNode(amount);
        newNode.appendChild( newTxt );
        node.appendChild( newNode );
    }

    var selectDate = function(e) {
        logger.debug("Enter selectDate()");

        var elem = getEventSource(e);
        logger.debug("ID: ", elem.id,
                   "\nStart Date: ", reservation.getStartDate(),
                   "\nEnd Date: ", reservation.getEndDate() );

        if( elem.id == null || elem.id == "" ||
            ! calendarDateRegex.test( elem.id ) ) {
            // The user clicked on something other than a selectable date
            return false;
        }

        if( reservation.getStartDate() == elem.id ) {

            reservation.setStartDate( "" );
            reservation.setEndDate( "" );

        } else if( reservation.getStartDate().length == 0 ||
            reservation.getEndDate().length > 0         ) {

            reservation.setStartDate( elem.id );
            reservation.setEndDate( "" );

        } else if( reservation.getEndDate().length == 0 ) {

            var tmpDate = reservation.getStartDate();
            var numDays = daysBetweenDateStrings( tmpDate, elem.id );
            if( numDays > MAX_DAYS_BETWEEN_START_END ) {
                logger.debug("Too many days between: ", numDays);
                reservation.setStartDate( elem.id );
                reservation.setEndDate( "" );
            } else if( reservation.getStartDate() > elem.id ) {
                       reservation.setStartDate( elem.id );
                reservation.setEndDate( tmpDate );
            } else {
                reservation.setEndDate( elem.id );
            }

        } else {
//            alert("Should not get here!");
        }

        self.updateCalendars();

        logger.debug("Exit selectDate()");
        return false;
    }

    this.updateCalendars = function() {
        logger.debug("Enter updateCalendars()");
        this.updateCalendar( self.leftCal );
        this.updateCalendar( self.rightCal );
        logger.debug("Exit updateCalendars()");
    }

    var ONE_DAY = 1000 * 60 * 60 * 24
    function daysBetweenDateStrings( dateStr1, dateStr2 ) {
        logger.debug("Enter daysBetweenDateStrings()");
        date1 = getDateFromIdString( dateStr1 );
        date2 = getDateFromIdString( dateStr2 );
        // The number of milliseconds in one day

        // Convert both dates to milliseconds
        var date1_ms = date1.getTime()
        var date2_ms = date2.getTime()

        // Calculate the difference in milliseconds
        var difference_ms = Math.abs(date1_ms - date2_ms)

        // Convert back to days and return
        logger.debug("Exit daysBetweenDateStrings()");
        return Math.round(difference_ms/ONE_DAY)
    }

    function getDateFromIdString( dateStr ) {
        var year  = "20" + dateStr.substr(0, 2);
        var month = dateStr.substr(2, 2);
        var day   = dateStr.substr(4, 2);
        var date = new Date( year, month - 1, day );
        return date;
    }

    var disableLeftRight = function() {
        logger.debug("Enter disableLeftRight()");

        jumpToDiv.onclick = function() { return false; };
        calLeft.onclick = null;
        calLeft.style.display = "none";
        calRight.onclick = null;
        calRight.style.display = "none";


        logger.debug("Exit disableLeftRight()");
    }

    var enableLeftRight = function() {
        logger.debug("Enter enableLeftRight()");

        var loaded = true;
        for( var i in calIdLoaded ) {
            logger.debug("CalId: ", i, " loaded? ", calIdLoaded[i]);
            loaded = loaded && calIdLoaded[i];
        }

        if( loaded ) {
            logger.debug("LOADED!");
            var leftMonth = calIdDate[self.leftCal].getMonth();
            var rightMonth = calIdDate[self.rightCal].getMonth();
            var todayMonth = today.getMonth();
            if( leftMonth != todayMonth ) {
                calLeft.onclick  = calendarLeft;
                var lm = leftMonth - 1;
                lm = (lm<0) ? 11 : lm;
                calLeft.innerHTML = months[lm];
                calLeft.style.display = "block";
            }
            var check = rightMonth - todayMonth
            if(  check != -2 && check != 10 ) {
                calRight.onclick = calendarRight;
                calRight.innerHTML = months[ (rightMonth+1)%12 ];
                calRight.style.display = "block";
            }

            jumpToDiv.onclick = loadCalendarsForDate;

        }

        logger.debug("Exit enableLeftRight()");
    }

    var calendarRight = function() {
        logger.debug("Enter calendarRight()");

        disableLeftRight();
        var cal1      = document.getElementById( self.leftCal );
        var cal2     = document.getElementById( self.rightCal );
        cal1.innerHTML = cal2.innerHTML;
        calIdDate[self.leftCal] = calIdDate[self.rightCal];
        var tDate = getNextMonthString( calIdDate[self.rightCal] );
        self.getCalendar(self.rightCal, tDate);

        logger.debug("Exit calendarRight()");
        return false;
    }

    function getNextMonthString( date ) {
        logger.debug("Enter getNextMonthString()");

        var year = date.getFullYear();
        var month = date.getMonth();
        if( month == 11 ) {
            month = 1;
            year += 1;
        } else {
            month += 2;
        }
        if( month < 10 ) {
            month = "0" + month;
        }
        tYear = "" + year;
        tDate = "" + tYear.substring(2,4) + month;

        logger.debug("Exit getNextMonthString()");
        return tDate;
    }

    var calendarLeft = function() {
        logger.debug("Enter calendarLeft()");
        disableLeftRight();
        var cal1      = document.getElementById( self.leftCal );
        var cal2     = document.getElementById( self.rightCal );
        cal2.innerHTML = cal1.innerHTML;
        calIdDate[self.rightCal] = calIdDate[self.leftCal];
        var year = calIdDate[self.leftCal].getFullYear();
        var month = calIdDate[self.leftCal].getMonth();
        if( month == 0 ) {
            month = 12;
            year -= 1;
        }
        if( month < 10 ) {
            month = "0" + month;
        }
        tYear = "" + year;
        tDate = "" + tYear.substring(2,4) + month;
        self.getCalendar(self.leftCal, tDate);

        logger.debug("Exit calendarLeft()");
        return false;
    }

}


