//****************************************************
//                         Global vars
//****************************************************
var res = new reservation();
var today = new Date();
var maxSledWeight = 350;
var maxCartWeight = 500;
var maxScooterWeight = 300;

function loadRes()
{
   // Add each tab to the global tabs variable defined in tabs.js
   // Base level
   tabs.push(new tab('base', '', 0, 'new;old', false));
   // Level 0
   tabs.push(new tab('new', 'New Reservation',     1, 'cart;scooter;kt;sled',false));
   tabs.push(new tab('old', 'Existing Reservation',1, 'allServices', false));
   // Level 1
   tabs.push(new tab('cart',       'Cart Ride',       2, 'date;contact;riders;match;review;pay',false));
   tabs.push(new tab('scooter',    'Scooter Ride',    2, 'date;contact;riders;match;review;pay',false));
   tabs.push(new tab('kt',         'Kennel Tour',     2, 'date;contact;review;pay',             false));
   tabs.push(new tab('sled',       'Winter Sled Ride',2, 'date;contact;riders;match;review;pay',false));
   tabs.push(new tab('allServices','All Services',    2, 'login;loginReview;pay',               false));
   // Level 2
   tabs.push(new tab('contact','Contact Info',3, '', true));
   tabs.push(new tab('date',   'Date/Time',   3, '', true));
   tabs.push(new tab('review', 'Review',      3, '', true));
   tabs.push(new tab('pay',    'Payment',     3, '', true));
   tabs.push(new tab('riders', 'Riders',      3, '', true));
   tabs.push(new tab('match',  'Fill Seats',  3, '', true));
   tabs.push(new tab('login',       'Login',  3, '', true));
   tabs.push(new tab('loginReview', 'Review', 3, '', true));

   res.loadProgress();
   res.showProgress('contact');
   res.presetVals();
   buildTabHTML();
   changeTab(0);
   tabsBuilt=true;
}

//****************************************************
//                         Object definitions
//****************************************************

//
//    Object that holds all the selected sleds in an array
//
function reservation()
{
   // These first variables correspond directly to fields in the database
   this.resID = '';
   this.restakerID = 0;       // 0 = website, 1 = Tracie, 2 = Jeff
   this.affCode = '';
   this.name = '';
   this.email = '';
   this.arrivalDate = '';
   this.mobilePhone = '';
   this.localPhone = '';
   this.lodging = '';
   this.comment = '';

   this.type = 'cart';     // kt = kennel tour, cart = cart ride, sled = sled ride
   this.lodgingText = '';
   this.kts = new Array();
   this.sleds = new Array();
   this.scooters = new Array();
   this.riders = new Array();
   this.emailVerified = false;
   this.weightInstructions = false;
   this.maxWeight = maxSledWeight;
   this.totCost = 0;
   this.progress = new Array();

   // Kennel Tour methods
   this.addKT = addKT;
   this.removeKT = removeKT;
   this.showSelectedKT = showSelectedKT;
   this.resetSelectedKT = resetSelectedKT;

   // Review methods
   this.showKTReview = showKTReview;
   this.showSledReview = showSledReview;
   this.resInfoText = resInfoText;
   this.resInfoFooter = resInfoFooter;

   // Ride mehods
   this.getSledByIndex = getSledByIndex;
   this.findSledIndex = findSledIndex;
   this.numSleds = numSleds;
   this.addSled = addSled;
   this.removeSled = removeSled;
   this.sortSleds = sortSleds;
   this.drawSelectedSledsTable = drawSelectedSledsTable;
   this.drawMatchSledsTable = drawMatchSledsTable;
   this.checkStoredSleds = checkStoredSleds;
   this.allSledsFull = allSledsFull;

   // Rider methods
   this.getRiderByIndex = getRiderByIndex;
   this.findRiderIndex = findRiderIndex;
   this.numRiders = numRiders;
   this.addRider = addRider;
   this.removeRider = removeRider;
   this.sortRiders = sortRiders;
   this.showRiders = showRiders;
   this.showMatchRiders = showMatchRiders;
   this.allRidersSeated = allRidersSeated;

   this.seatRider = seatRider;
   this.unSeatRider = unSeatRider;

   // Progress methods
   this.loadProgress = loadProgress;
   this.toggleProgress = toggleProgress;
   this.showProgress = showProgress;

   // Misc. methods
   this.presetVals = presetVals;
}

//*****************************************************************
//          Kennel Tour handling methods of the reservation object
//*****************************************************************

function addKT(ktID, day, time, adult, child, free)
{
   var ind = -1;

   // See if this tour has already been selected
   var l = this.kts.length;
   for(var i=0; i<l; i++)
   {
      if(this.kts[i].id == ktID)
      {
         ind = i;
         break;
      }
   }

   if(ind >= 0)
   {
      // Kennel tour with this id already selected.  Just update the counts
      this.kts[ind].adult = adult;
      this.kts[ind].child = child;
      this.kts[ind].free = free;
      this.kts[ind].cost = 15*adult + 8*child;
   }
   else
   {
      // Kennel tour with this id has not been selected yet.  Add it.
      this.kts.push(new ktObj(ktID, day, time, adult, child, free));
   }
}

function removeKT(i)
{
   this.kts.splice(i,1);
}

function resetSelectedKT()
{
   var kt;
   var l = this.kts.length;

   for(var i=0; i<l; i++)
   {
      kt = this.kts[i];
      setSelectValue('ktAdult'+kt.id, kt.adult);
      setSelectValue('ktChild'+kt.id, kt.child);
      setSelectValue('ktFreee'+kt.id, kt.free);
   }
}

function showSelectedKT()
{
   var out = '';
   var l = this.kts.length;
   for(var i=0; i<l; i++)
   {
      out += '<p><button type="button" onclick="removeKTour('+i+')">X</button>';
      out += this.kts[i].displayText();
   }
   if(out == '')
      out = '<p>You have no kennel tours selected.</p>';
   document.getElementById('selectedStuff').innerHTML = out;
}

//*****************************************************************
//          Sled handling methods of the reservation object
//*****************************************************************

function checkStoredSleds()
{
   for(i = 0; i < this.numSleds(); i++)
   {
      sled = this.sleds[i];
      x = document.getElementById(sled.id);

      if(x)
      {
         x.checked = true;
         x.parentNode.className = "sledStatusHold";
      }
   }
}

function getSledByIndex(i)
{
   return this.sleds[i];
}

function findSledIndex(id)
{
   var found = false;

   for(var i = 0; i < this.numSleds(); i++)
   {
      if(this.sleds[i].id == id)
      {
         found = true;
         break;
      }
   }

   return found ? i : -1;
}

function numSleds()
{
   return this.sleds.length;
}

function addSled(newSled)
{
   this.sleds.push(newSled);
   this.sleds.sort(this.sortSleds);
}

function removeSled(oldSled)
{
   var i = this.findSledIndex(oldSled.id);

   if(i >= 0)
      this.sleds.splice(i,1);
}

function sortSleds(a, b)
{
   return ((a.id < b.id) ? -1 : ((a.id > b.id) ? 1 : 0));

}

function drawSelectedSledsTable()
{
   var output = '';
   var num = this.numSleds();

   if(num == 0)
   {
      // output = "<h1>You have no "+this.type+"s selected</h1>";
      output = "";
   }
   else
   {
      output = '<h1>You have '+num+' '+this.type+'s selected</h1>\n';
      output += '<h2>'+num+' '+this.type+'s can hold from '+num+' to '+num*3+' people, depending on their size.</h2><br />\n';
      output += '<table cellspacing="0" cellpadding="0"><tbody>';

      for(var i = 0; i < num; i++)
      {
         output += "<tr><th>" + this.sleds[i].sdate + " at " + this.sleds[i].stime + "</th>";
         output += "<td><button onclick=\"toggleSled('" + i + "','index')\" type=\"button\">Remove "+this.type+"</button></td></tr>";
      }

      output += "</tbody></table>";
      output += "<br /><p>You may select more "+this.type+"s, or <button type=\"button\" onclick=\"changeTabByID('contact')\">Move to the next section</button></p>";
   }

   var x = document.getElementById("selectedStuff");
   x.innerHTML = output;
}

function drawMatchSledsTable()
{
   var output = '';
   var k;

   if(this.numSleds() == 0)
      output = "<h1>No "+this.type+"s selected</h1>";
   else
   {
      output = '<h1>Selected '+this.type+'s</h1>\n<dl class="seatSelection">';

      for(var i = 0; i < this.numSleds(); i++)
      {
         output += "<dt id=\"m" + this.sleds[i].id + "\">" + this.sleds[i].sdate + " at " + this.sleds[i].stime + "</dt>";
         if(this.sleds[i].weight == 0)
            output += "<dd>There are no riders in this "+this.type+".  Add up to 3 people and "+this.maxWeight+" pounds.</dd>";
         else
         {
            var remaining = this.maxWeight - this.sleds[i].weight;
            output += "<dd>Cost: $" + this.sleds[i].cost + ".  Weight: " + this.sleds[i].weight + " pounds.  You have "+remaining+" pounds left.</dd>";
         }

         for(j=0; j<3; j++)
         {
            k = j+1;
            if(this.sleds[i].seats[j])
               output += "<dd>Seat "+k+": "+this.sleds[i].seats[j].substring(2)+" <button type=\"button\" onclick=\"res.unSeatRider('"+this.sleds[i].seats[j]+"')\">Unseat "+this.sleds[i].seats[j].substring(2)+" -&gt;</button></dd>";
            else
            {
               output += "<dd><input onclick=\"res.showMatchRiders()\" type=\"radio\" name=\"sledSeat\" id=\"seat"+i+k+"rad\" value=\""+j+this.sleds[i].id+"\"/><label for=\"seat"+i+k+"rad\">Seat "+k+" Empty</label></dd>";
               break;
            }
         }
      }
      output += "</dl>";
   }

   var x = document.getElementById("matchSledsDIV");
   x.innerHTML = output;
}

function allSledsFull()
{
   var result = true;

   if(this.numSleds() > 0)
   {
      for(var i = 0; i < this.numSleds(); i++)
      {
         if(!this.sleds[i].seats[0])
            result = false;
      }
   }
   else
      result = false;

   return result;
}

//*****************************************************************
//          Review tab handling methods
//*****************************************************************

function showKTReview()
{
   var l = this.kts.length;
   var out = this.resInfoText();
   this.totCost = 0;
   out += '<h1>Please review your kennel tour selection</h1>\n';
   out += '<table cellspacing="0" cellpadding="0" class="reviewTable">';
   for(var i=0; i<l; i++)
   {
      this.totCost += this.kts[i].cost;
      out += '<tr><th>'+this.kts[i].displayText()+'</th></tr>';
      
   }
   out += '</table>';
   out += this.resInfoFooter();
   document.getElementById("resReviewDIV").innerHTML = out;
}

function showSledReview()
{
   var out = '';

   if(res.allRidersSeated() && res.allSledsFull() && res.emailVerified)
   {
      res.totCost = 0;
      out += this.resInfoText();
      out += '<h1>Please review your '+this.type+' information</h1>';
      out += '<table cellspacing="0" cellpadding="0" class="reviewTable">';
      var num = res.numSleds();
      for(var i = 0; i < num; i++)
      {
         res.totCost += res.sleds[i].cost;
         out += '<tr><th>'+res.sleds[i].riderNameText()+' riding on '+res.sleds[i].sdate+' at '+res.sleds[i].stime+' weighing '+res.sleds[i].weight+' and costs $'+res.sleds[i].cost+'</th></tr>';
      }
      out += '</table>';
      out += this.resInfoFooter();
      document.getElementById("resReviewDIV").innerHTML = out;
   }
   else
   {
      if(!res.emailVerified)
         alert('Your email address has not been verified.  Go back to the "Contact Info" tab and enter your email address.');
      else if(!res.allRidersSeated())
         alert('Not all of your riders have been seated.  Go to the "Fill Seats" tab to fix.');
      else if(!res.allSledsFull())
         alert('Not all of your sleds have riders.  Go to the "Fill Seats" tab to fix.');
   }
}

function resInfoText()
{
   var output = '<p class="c"><button class="bigButt" type="button" onclick="doResHold()">Make Reservation</button></p>';
   output += '<h1>Please review your contact information</h1>\n';
   output += '<table cellspacing="0" cellpadding="0" class="reviewTable">';
   output += '<tr><th>Reservation Name:</th><td>'+this.name+'</td></tr>';
   output += '<tr><th>Arrival Date:</th><td>'+this.arrivalDate+'</td></tr>';
   output += '<tr><th>Confirmed email address:</th><td>'+this.email+'</td></tr>';
   output += '<tr><th>Mobile Phone Number:</th><td>'+this.mobilePhone+'</td></tr>';
   output += '<tr><th>Local Phone Number:</th><td>'+this.localPhone+'</td></tr>';
   output += '<tr><th>Lodging:</th><td>'+this.lodgingText+'</td></tr>';
   if(this.affCode)
      output += '<tr><th>Referral Code:</th><td>'+this.affCode+'</td></tr>';
   output += '<tr><th>Optional Comment:</th><td>'+this.comment+'</td></tr>';
   output += '</table>';

   return output;
}

function resInfoFooter()
{
   var output = '</ol></li>';
   output += '<li>The total cost of this reservation is $'+this.totCost+'</li>';
   output += '<p class="c"><button class="bigButt" type="button" onclick="doResHold()">Make Reservation</button></p>';
   output += '<br />(If your reservation details are not correct, go back to the appropriate section and make your changes.)';

   return output;
}

function getRiderByIndex(i)
{
   return this.riders[i];
}

function findRiderIndex(id)
{
   var found = false;

   for(var i = 0; i < this.numRiders(); i++)
   {
      if(this.riders[i].id == id)
      {
         found = true;
         break;
      }
   }

   return found ? i : -1;
}

function numRiders()
{
   return this.riders.length;
}

function addRider(newRider)
{
   this.riders.push(newRider);
   this.riders.sort(this.sortRiders);
}

function removeRider(i)
{
   this.riders.splice(i,1);
}

function sortRiders(b, a)
{
   return ((a.rweight < b.rweight) ? -1 : ((a.rweight > b.rweight) ? 1 : 0));

}

function showRiders()
{
   var output = '';
   var num = this.numRiders();
   var num2 = this.numSleds();

   if(num == 0)
//      output = "<h1>You have no riders entered.</h1>";
      output = "";
   else
   {
      output = "<h1>You have "+num+" riders entered.</h1><br /><br />";

      if(num < num2)
         output += '<h2>You have '+num2+' '+this.type+'s selected, so you need to enter at least '+(num2*1-num)+' more riders</h2>';
      else
         output += '<h2>Enter more riders or <button type="button" onclick="changeTabByID(\'match\')">Move to the next section</button></h2>';

      output += '<br /><br /><table cellspacing="0" cellpadding="0"><tbody>';
      output += "<tr><th>Name</th><th>Weight (pounds)</th><th>Height</th><th>Age</th><th>&nbsp;</th></tr>";

      for(var i = 0; i < this.numRiders(); i++)
      {
         output += "<tr><th>" + this.riders[i].rname + "</th><td>" + this.riders[i].rweight + "</td><td>" + this.riders[i].rheightText + "</td><td>" + this.riders[i].rageText + "</td>";
         output += '<td><button onclick="doRemoveRider('+i+')" type="button">Remove ' + this.riders[i].rname + '</button></td></tr>';
      }

      output += "</tbody></table>";
   }

   var x = document.getElementById("viewRiderDIV");
   x.innerHTML = output;
}

function showMatchRiders()
{
   var output = '';

   if(this.numRiders() == 0)
      output = "<h1>Enter rider info and press Add Rider</h1>";
   else
   {
      var limit = calculateWeightLimit();
      var rows = '';                         // string for the table rows of unseated riders
      output = '<table cellspacing="0" cellpadding="0"><tbody>';
      output += "<tr><th>&nbsp;</th><th>Name</th><th>Weight (pounds)</th><th>Height</th><th>Age</th></tr>";

      for(var i = 0; i < this.numRiders(); i++)
      {
         if(!this.riders[i].sledID)
         {
            if(this.riders[i].rweight <= limit)
               rows += '<tr><td><button onclick="res.seatRider(' + i + ')" type="button">&lt;-Seat ' + this.riders[i].rname + '</button></td>';
            else
               rows += '<tr><td>&nbsp;</td>';
            rows += "<th>" + this.riders[i].rname + "</th><td>" + this.riders[i].rweight + "</td><td>" + this.riders[i].rheightText + "</td><td>" + this.riders[i].rageText + "</td></tr>";
         }
      }

      if(!rows)
      {
         output = "<h1>All riders have been seated</h1>";
         output += '<button type="button" onclick="changeTabByID(\'review\')">Move to the next section</button>';
      }
      else
         output += rows + "</tbody></table>";
   }

   var x = document.getElementById("matchRidersDIV");
   x.innerHTML = output;
}

function allRidersSeated()
{
   var result = true;

   if(this.numRiders() > 0)
   {
      for(var i = 0; i < this.numRiders(); i++)
      {
         if(!this.riders[i].sledID)
            result = false;
      }
   }
   else
      result = false;

   return result;
}

function seatRider(riderIndex)
{
   var val = getRadioVal('sledSeat');

   if(val)
   {
      var rider = this.riders[riderIndex];

      // Extract hidden info from checked radio buttons value
      var seat = val.substring(0,1);
      i = this.findSledIndex(val.substring(1));
      var sled = this.getSledByIndex(i);

      sled.seats[seat] = rider.id;
      rider.sledID = sled.id;

      sled.weight += rider.rweight;
      sled.updateSledCost();

      this.drawMatchSledsTable();
      this.showMatchRiders();
   }
   else
   {
      alert('You must select a sled seat before seating a rider.');
   }
}

function unSeatRider(riderID)
{
   var i = this.findRiderIndex(riderID);
   var rider = this.getRiderByIndex(i);

   if(rider.sledID)
   {
      var j = this.findSledIndex(rider.sledID);
      var sled = this.getSledByIndex(j);

      var k = sled.seats[0] == rider.id ? 0 : (sled.seats[1] == rider.id ? 1 : 2);
      sled.seats.splice(k,1);
      sled.seats[3] = '';
      sled.weight -= rider.rweight;
      sled.updateSledCost();      
   }

   rider.sledID = '';

   this.drawMatchSledsTable();
   this.showMatchRiders();

}

function loadProgress()
{
   this.progress[0] = new infoObj('resName',    'Reservation Name',   'contact', false, 'The name associated with the reservation.  This could be the name of the organizor, or something like "The Martin Family"');
   this.progress[1] = new infoObj('mobilePhone','Mobile Phone',       'contact', false, 'Your mobile telephone number.  Please include your area code.  We can not accept international numbers.');
   this.progress[2] = new infoObj('lodging',    'Lodging',            'contact', false, 'Where you are staying');
   this.progress[3] = new infoObj('localPhone', 'Local Phone',        'contact', false, 'The phone number where you are staying locally.  Use your mobile phone number if you are coming up for the day or do not know your local number.  The local area code is (970)');
   this.progress[4] = new infoObj('comment',    'Special Notes',      'contact', true,  'Any special instructions you may have for us, like if you are pregnant or if anyone has disabilities requiring special care.');
   this.progress[5] = new infoObj('affCode',    'Referral Code',      'contact', true, 'Optional.  If you do not have or do not know what a referral code is, leave this field empty.');
   this.progress[6] = new infoObj('emailAddr1', 'Email Address',      'contact', false, 'It is important that our system be able to commincate with you via email.  Please enter your email address.');
   this.progress[7] = new infoObj('emailAddr2', 'Email Address Again','contact', false, 'We just want to be sure you have entered your email address correctly.');
   this.progress[8] = new infoObj('mBeginDate,dBeginDate,yBeginDate','Begin Date','date', false, 'Enter the date you want to begin looking for availability.  This is usually your arrival date into Grand County.  Please use the month/day/year date format.');
   this.progress[9] = new infoObj('mEndDate,dEndDate,yEndDate',      'End Date',  'date', false, 'Enter the date you want to see availability through.  This is usually your departure date from Grand County.  Please use the month/day/year date format.');
   this.progress[10] = new infoObj('ktAdult', 'Number of adults',   'date', false, 'Enter the number of people in your party who are 13 years old or older.');
   this.progress[11] = new infoObj('ktChild', 'Number of children', 'date', false, 'Enter the number of children in your party who are between the ages of 4 and 12.');
   this.progress[12] = new infoObj('ktFree',  'Number of toddlers', 'date', false, 'Enter the number of children in your party who are 3 years old or younger.');
   this.progress[13] = new infoObj('reviewButt', 'Review reservation', 'review', false, 'Click the button to see a summary of your reservation.  You do not have a reservation yet.');
   this.progress[14] = new infoObj('pay', 'Payment', 'pay', false, 'Fill in the form to make your payment.');
   this.progress[15] = new infoObj('riderName',   'Rider Name',   'riders', false, 'Enter a unique name for each rider.');
   this.progress[16] = new infoObj('riderWeight', 'Rider Weight', 'riders', false, 'Weigh yourself at home in your winter gear, or add 5 to 15 pounds to your bathroom weight to get your winter sled riding weight.');
   this.progress[17] = new infoObj('weightUnits', 'Weight Units', 'riders', true, 'Choose the units for the weight you entered.  We will convert your weight to pounds.');
   this.progress[18] = new infoObj('riderHeight', 'Rider Height', 'riders', true, 'Choose either taller than or shorter than 48 inches.');
   this.progress[19] = new infoObj('riderAge',    'Rider Age',    'riders', true, 'Choose the appropriate age for each rider.  The cost of the sled is determined by the ages of the riders.');
   this.progress[20] = new infoObj('sledSeat', 'Seat Riders', 'match', true, 'Click the radio button of the seat you want to fill.  All the riders that can fit in that seat will have a seating button.  Click the button of the rider you want to put in that seat.');
   this.progress[21] = new infoObj('resID',    'Reservation ID', 'login', false, 'This is the reservation ID that was generated when you made your reservation.  Check the email we sent to confirm your reservation.');
   this.progress[22] = new infoObj('resEmail', 'Email Address',  'login', false, 'Enter the email address you entered when you made your reservation.  This is kind of like your password for accessing your reservation details.');
}

function showProgress(group)
{
   var o = '<dl class="progress">';
   var l = this.progress.length;

   for(var i=0; i<l; i++)
   {
      if(this.progress[i].group == group)
      {
         o += '<dt><button type="button" onclick="showDD(\''+this.progress[i].id+'PDD\')">?</button>'+this.progress[i].name+'</dt>';
         o += '<dd id="'+this.progress[i].id+'PDD">'+this.progress[i].helpText+'</dt>';
      }
   }

   o += '</dl>';
   document.getElementById('progress').innerHTML = o;
}

//
// Function:   toggleProgress(id, state)
// Usage:      Called when an input field is changed.  Changes label text class to complete or incomplete
//    Also checks to see if all other input fields in this group are complete.  If so, changes label of group.
//
function toggleProgress(id, state)
{
   var x;
   var groupName = '';
   var groupComplete = true;
   var len = this.progress.length;

   // find the infoObj with the provided id and change the label.  also remember what group it is in
   for(var i = 0; i < len; i++)
   {
      if(this.progress[i].id == id)
      {
         this.progress[i].complete = state;
         x = document.getElementById(id+'Label');
         if(x) x.className = state ? "complete" : "incomplete";
         groupName = this.progress[i].group;
         break;
      }
   }

   // Check to see if the group is complete
   for(i = 0; i < len; i++)
   {
      if(this.progress[i].group == groupName)
      {
         if(!this.progress[i].complete)
         {
            groupComplete = false;
            break;
         }
      }
   }

   if(groupName == 'contact')
   {
      // If the group is complete show it's next button
      x = document.getElementById('contactNextDIV');
      if(x)
      {
         x.style.display = groupComplete ? "block" : "none";
         x = document.getElementById(groupName+'NextButt');
         if(x && groupComplete) x.focus();
      }
   }
}

function presetVals()
{
   res.affCode = document.getElementById('affCode').value;
   res.arrivalDate = getSelectValue('mArrivalDate')+'/'+getSelectValue('dArrivalDate')+'/'+getSelectValue('yArrivalDate');
}

//****************************************************************
//                Kennel Tour object
//****************************************************************

function ktObj(id, day, time, a, c, f)
{
   this.id = id;
   this.day = day;
   this.time = time;
   this.adult = a;
   this.child = c;
   this.free = f;
   this.cost = 15*a + 8*c;

   this.displayText = displayText;
}

function displayText()
{
   var out = this.day+' at '+this.time+' for ';
   out += this.adult+' adults, '+this.child+' children and '+this.free+' toddlers.  ';
   out += 'Total cost is $'+this.cost+'</p>';

   return out;
}


//
//    Sled object
//
function sledObj(id)
{
   this.id = id;

   var d = new Date();
   d.setDate(id.substring(8, 10));
   var m = id.substring(5, 7) - 1;
   d.setMonth(m);
   d.setFullYear(id.substring(0, 4));
   this.sdate  = d.toDateString();

   this.stime = id.substring(10, 15);
   this.snumber = id.substring(15);
   this.seats = new Array(3);
   this.seats[0] = '';
   this.seats[1] = '';
   this.seats[2] = '';
   this.cost = 0;
   this.weight = 0;

   this.toggle = sledToggle;
   this.updateSledCost = updateSledCost;
   this.riderNameText = riderNameText;
}

//
// Toggle sled selected or deselected
//
function sledToggle(state)
{
   // Add or remove sled from sleds
   if(state)
      res.addSled(this);
   else
      res.removeSled(this);

   // If sled calendar is visible, toggle checkbox
   var x = document.getElementById(this.id);

   if(x)
   {
      x.checked = state;
      x.parentNode.className = state ? "sledStatusHold" : "sledStatus0";
   }

   //  We have added or removed a sled, so reset the confirm button
   resetReview();
}

function updateSledCost()
{
   if(res.type == 'cart')
      this.cost = 135;
   else if(res.type == 'scooter')
      this.cost = 75;
   else
   {
      this.cost = 0;
      var peep = new Array();

      for(var i=0; i<this.seats.length; i++)
         if(this.seats[i])
            peep[i] = this.seats[i].substring(0,1);

      peep.sort();

      for(i=0; i<this.seats.length; i++)
      {
         switch(peep[i])
         {
            case 'A' :
               this.cost += (i == 0) ? 135 : (i == 1) ? 50 : 25;
               break;
            case 'C' :
               if(i == 0)
                  this.cost += 135;
               else if(i == 1)
               {
                  if(peep[0] == 'A')
                     this.cost += 25;
               }
               else
                  this.cost += 25;
               break;
         }
      }
   }
}

function riderNameText()
{
   var names = this.seats[0].substring(2);

   if(this.seats[1] && this.seats[2])  
      names += ', ' + this.seats[1].substring(2) + ' and ' + this.seats[2].substring(2);
   else if(this.seats[1])
      names += ' and ' + this.seats[1].substring(2);

   return names;
}

//
//    Rider object
//
function riderObj(rname, rweight, rheightID, rheightText, rageID, rageText)
{
   this.id = rageID + rheightID + rname;
   this.rname = rname;
   this.rweight = rweight;
   this.rheightID = rheightID;
   this.rheightText = rheightText;
   this.rageID = rageID;
   this.rageText = rageText;
   this.sledID = '';
}

//
// Info object
//
function infoObj(id, name, group, state, help)
{
   this.id = id;
   this.name = name;
   this.complete = state;
   this.group = group;
   this.helpText = help;
}

//****************************************************
//                         Functions
//****************************************************
function localChangeTab(ind)
{
   switch(tabs[ind].level)
   {
      case 2 :
         // Second level selected. Either kt, scooter, cart or sled
         res.type = tabs[ind].theId;
         res.kts = new Array();
         res.sleds = new Array();
         res.scooters = new Array();
         res.riders = new Array();
         res.weightInstructions = false;
         res.totCost = 0;
         if(res.type == 'kt')
            res.showSelectedKT()
         else
         {
            if(res.type == 'cart')
               res.maxWeight = maxCartWeight;
            else if(res.type == 'scooter')
               res.maxWeight = maxScooterWeight;
            else
               res.maxWeight = maxSledWeight;

            res.drawSelectedSledsTable();
         }

         // This must be a new service selection, so clear the calendar section
         document.getElementById('avCalendar').innerHTML = '';

         // Change the picture on the left to match the service
         var x = document.getElementById('servicePic');
         if(x) x.src = '/images/' + res.type + '.jpg';

         break;         
      case 3 :
         // Third level selected.  Div will change, so help on left needs to change
         res.showProgress(tabs[ind].theId);
         // If this is the rider tab, need to show the appropriate details section
         if(tabs[ind].theId == "riders")
         {
            switch(res.type)
            {
               case 'cart' :
                  document.getElementById("sledRiderTypes").style.display = "none";
                  document.getElementById("cartRiderTypes").style.display = "block";
                  break;
               case 'sled' :
                  document.getElementById("sledRiderTypes").style.display = "block";
                  document.getElementById("cartRiderTypes").style.display = "none";
                  break;
            }
         }
         break;
   }
}

function setArrivalDate(obj)
{
   var prefix = obj.id.substring(0,1);
   var val = getSelectValue(obj.id);
   setSelectValue(prefix+'BeginDate', val);
   setSelectValue(prefix+'EndDate', val);

   res.arrivalDate = getSelectValue('mArrivalDate')+'/'+getSelectValue('dArrivalDate')+'/'+getSelectValue('yArrivalDate');
}

function setEndDate(obj)
{
   var id2 = obj.id.substring(0,1) + 'EndDate';
   var val = getSelectValue(obj.id);

   setSelectValue(id2, val);
}

function setTheYear(obj)
{
   var val = getSelectValue(obj.id);

   if(val < (today.getMonth() + 1))
   {
      setSelectValue('yBeginDate', today.getFullYear() + 1);
      setSelectValue('yEndDate',   today.getFullYear() + 1);
   }
   else
   {
      setSelectValue('yBeginDate', today.getFullYear());
      setSelectValue('yEndDate',   today.getFullYear());
   }
}


function validateEntry(x)
{
   var val = x.value;

   switch(x.id)
   {
      case 'resName' :
      case 'riderName' :
         var allowed = "abcdefghijklmnopqrstuvwxyz 0123456789";
         val = validateInput(x.id, val, allowed);
         break;
      case 'affCode' :
         var allowed = "abcdefghijklmnopqrstuvwxyz0123456789";
         val = validateInput(x.id, val.toUpperCase(), allowed);
         break;
      case 'emailAddr1' :
      case 'emailAddr2' :
      case 'resEmail' :
         var allowed = "abcdefghijklmnopqrstuvwxyz0123456789@.-_";
         val = validateInput(x.id, val, allowed);
         break;
      case 'mobilePhone' :
      case 'localPhone' :
         val = makePhoneNumber(val);
         x.value = val;
         if(val.length != 14) alert('Phone number does not appear valid');
         break;
      case 'riderWeight' :
         var allowed = "0123456789.";
         val = validateInput(x.id, val, allowed);
         break;
   }

   // toggle the progress of this input and possibly the group
   var state = val ? true : false;
   res.toggleProgress(x.id, state);

   // Save the new value to the res object
   switch(x.id)
   {
      case 'resName' :
         res.name = val;
         break;
      case 'mobilePhone' :
         res.mobilePhone = val;
         break;
      case 'localPhone' :
         res.localPhone = val;
         break;
      case 'comment' :
         res.comment = val;
         break;
      case 'emailAddr2' :
         checkEmailAddress();
         break;
      case 'affCode' :
         res.affCode = val;
         break;
   }

   // Reservation info has changed, so reset the review button
   resetReview();
}

function formatResID(x)
{
   var nums = '0123456789';
   var val = x.value;
   var new_val = '';
   var c = '';
   var l = Math.min(val.length, 12);
   
   // Step through each character of the input value
   // 012345678901
   // 9999-99-9999
   for(var i = 0; i < l; i++)
   {
      c = val.charAt(i)+'';
      // Check to see if the character is in the allowed string
      if((i == 4) || (i == 7))
      {
         if(c == '-')
            new_val += c;
      }
      else
      {
         if(nums.indexOf(c) >= 0)
            new_val += c;     // Append char to the end of the new value if legal
      }
   }

   if((new_val.length == 4) || (new_val.length == 7))
      new_val += '-';

   // Put the new value in the input field
   x.value = new_val;
}

function checkEmailAddress()
{
   var e1 = document.getElementById("emailAddr1");
   var e2 = document.getElementById("emailAddr2");
   var y = document.getElementById('emailAddr2Label');

   if(e1.value && (e1.value == e2.value))
   {
      res.email = e1.value;
      res.emailVerified = true;
      y.className = 'complete';
   }
   else
   {
      res.emailVerified = false;
      y.className = 'incomplete';
      alert('The email addresses you entered do not match.');
   }
}

function showWeightAlert()
{
   if(!res.weightInstructions)
   {
      if(res.type == 'sled')
         alert('Be sure to provide an accurate weight.  Add 5 to 15 pounds to your "bathroom weight" to account for winter clothing.\n\nIf you show up over the weight limit ('+res.maxWeight+' pounds per sled), one of the following will apply:\n   1. We will be unable to take you for your ride (Please see our cancellation policy)\n   2. One or more persons in your party will not be able to ride.\n   3. If we feel it is safe to accommodate your weight, you will be charged $1 per pound that you are over our current weight limit.');
      else if(res.type == 'cart')
         alert('Be sure to provide an accurate weight.\n\nIf you show up over the weight limit ('+res.maxWeight+' pounds per cart), one of the following will apply:\n   1. We will be unable to take you for your ride (Please see our cancellation policy)\n   2. One or more persons in your party will not be able to ride.\n   3. If we feel it is safe to accommodate your weight, you will be charged $1 per pound that you are over our current weight limit.');
      else
         alert('Be sure to provide an accurate weight.\n\nIf you show up over the weight limit ('+res.maxWeight+' pounds per scooter), one of the following will apply:\n   1. We will be unable to take you for your ride (Please see our cancellation policy)\n   2. If we feel it is safe to accommodate your weight, you will be charged $1 per pound that you are over our current weight limit.');
      res.weightInstructions = true;
      showDD('riderWeightPDD');
   }
}

//******************************************************
//	            Availability Functions
//******************************************************
function showAvailability()
{
   var beginDate = getSelectValue('mBeginDate')+'/'+getSelectValue('dBeginDate')+'/'+getSelectValue('yBeginDate');
   var endDate = getSelectValue('mEndDate')+'/'+getSelectValue('dEndDate')+'/'+getSelectValue('yEndDate');
   var args = "q=av"+res.type+"&o=html&bd="+beginDate+"&ed="+endDate;
   var msg = 'Fetching ' + tabs[currentTab[2]].displayText + 's .....';

	asProcess('/winterpark/reservations/res_util.php', args, msg, handleAvailability, "avCalendar");
}

function handleAvailability()
{
	if(xmlHttp.readyState == 4)
	{
		document.getElementById("avCalendar").innerHTML = xmlHttp.responseText;
      switch(res.type)
      {
         case 'kt' :
            res.resetSelectedKT();
            break;
         case 'cart' :
         case 'scooter' :
         case 'sled' :
            res.checkStoredSleds();
            break;
      }
   }
}

//******************************************************
//	            Kennel Tour Functions
//******************************************************

function tourSelect(x)
{
   var ktID = x.id.substring(7);

   // Get number of each type of guest; cost
   var adult = getSelectValue('ktAdult'+ktID) * 1;
   var child = getSelectValue('ktChild'+ktID) * 1;
   var free  = getSelectValue('ktFreee'+ktID) * 1;
   var day = document.getElementById("ktDay"+ktID).innerHTML;
   var time = document.getElementById("ktTime"+ktID).innerHTML;

   res.addKT(ktID, day, time, adult, child, free);
   res.showSelectedKT();
   resetReview();
}

function removeKTour(i)
{
   var ktID = res.kts[i].id;

   setSelectValue('ktAdult'+ktID, 0);
   setSelectValue('ktChild'+ktID, 0);
   setSelectValue('ktFreee'+ktID, 0);

   res.removeKT(i);
   res.showSelectedKT();
}

//******************************************************
//	            Sled Functions
//******************************************************

function toggleSled(ent, entType)
{
   // entType is either a checkbox id, or an array index
   var sled;
   var state;

   switch(entType)
   {
      case "id":
         // We have a checkbox id
         var x = document.getElementById(ent);
         sled = new sledObj(ent);
         state = x.checked;
         break;
      case "index":
         // We have an index into the sledArray
         sled = res.getSledByIndex(ent);
         // Since we have an index into the sled array, the sled necessarily exists, so we are toggling it false
         state = false;
         break;
   }

   sled.toggle(state);

   res.drawSelectedSledsTable();
   res.drawMatchSledsTable();
}

function changeLodge(xs)   // x is the select DOM object
{
   // The value of the lodging options is lodgingID;lodgingPhoneNumber
   // Extract these values and save them to appropriate places.

   var xo = xs.options[xs.selectedIndex];

   if(xo.value != 'noselection')
   {
      res.toggleProgress("lodging", true);
      res.lodgingText = xo.text;
      var a = xo.value.split(";");
      res.lodging = a[0];

      if(a[1] == '')
         a[1] = document.getElementById("mobilePhone").value;

      document.getElementById("localPhone").value = a[1];
      res.localPhone = a[1];

      res.toggleProgress("localPhone", a[1]);
   }
   else
   {
      res.toggleProgress('lodging', false);
      res.toggleProgress('localPhone', false);
      document.getElementById("localPhone").value = '';
      res.localPhone = '';
      res.lodging = '';
      res.lodgingText = '';
   }
}


function calculateWeightLimit()
{
   var val = getRadioVal('sledSeat');
   var limit = 0;

   if(val)
   {
      var i = res.findSledIndex(val.substring(1));
      var sled = res.getSledByIndex(i);

      limit = res.maxWeight - sled.weight;
   }

   return limit;
}

//******************************************************
//	            Login Tab Functions
//******************************************************

function login()
{
   var args = 'q=l&o=xml';
   args += '&r=' + document.getElementById('resID').value;
   args += '&e=' + document.getElementById('resEmail').value;

	asProcess('/winterpark/reservations/res_util.php', args,'Fetching reservation...', handleLogin, "loginResultsDIV");
}

function handleLogin()
{
	if(xmlHttp.readyState == 4)
	{
      var message = '';
		var xmlDoc = xmlHttp.responseXML;
//		var r = xmlDoc.getElementsByTagName("result");
      var errorCount = xmlDoc.getElementsByTagName("errorCount")[0].childNodes[0].nodeValue * 1;

      if(errorCount > 0)
      {
         message = xmlDoc.getElementsByTagName("errorText")[0].childNodes[0].nodeValue;
      }
      else
      {
         res.resID = xmlDoc.getElementsByTagName("resID")[0].childNodes[0].nodeValue;
         res.email = xmlDoc.getElementsByTagName("email")[0].childNodes[0].nodeValue;
         res.totCost = xmlDoc.getElementsByTagName("balance")[0].childNodes[0].nodeValue * 1;

         updatePaymentForm();
   		document.getElementById("item_number").value = res.resID;
         message = "Reservation Found.  Click on the 'Payment' tab to make a payment.";
      }

      document.getElementById("loginResultsDIV").innerHTML = '<h1>'+message+'</h1>';
		document.getElementById("loginReviewDIV").innerHTML = '<h1>'+message+'</h1>';
   }
}

//******************************************************
//	            Review Tab Functions
//******************************************************

function resetReview()
{
   document.getElementById("resReviewDIV").innerHTML = '<button onclick="showResReview()" type="button" id="reviewButt">Click to review your reservation details</button>';
}

function showResReview()
{
   switch(res.type)
   {
      case 'kt' :
         res.showKTReview();
         break;
      case 'cart' :
      case 'scooter' :
      case 'sled' :
         res.showSledReview();
         break;
   }
}

function doResHold()
{
   var args = 'q=hold'+res.type+'&o=xml';
   args += '&rn=' + res.name;
   args += '&e=' + res.email;
   args += '&a=' + res.arrivalDate;
   args += '&m=' + res.mobilePhone;
   args += '&l=' + res.localPhone;
   args += '&lo=' + res.lodging;
   args += '&ac=' + res.affCode;
   args += '&c=' + res.comment;

   switch(res.type)
   {
      case 'kt' :
         args += getKTArgs();
         break;
      case 'cart' :
      case 'scooter' :
      case 'sled' :
         args += getSledArgs();
         break;
   }

	asProcess('/winterpark/reservations/res_util.php', args,'Recording reservation...', handleReservation, "reviewDIV");
}

function getKTArgs()
{
   var args = '';

   // Put rider info in args
   var ids = '';
   var a = '';
   var c = '';
   var f = '';
   var p = '';

   for(var i=0; i<res.kts.length; i++)
   {
      ids += res.kts[i].id + ';';
      a += res.kts[i].adult + ';';
      c += res.kts[i].child + ';';
      f += res.kts[i].free + ';';
      p += res.kts[i].cost + ';';
   }

   args += '&kti=' + ids;
   args += '&kta=' + a;
   args += '&ktc=' + c;
   args += '&ktf=' + f;
   args += '&ktp=' + p;

   return args;
}

function getSledArgs()
{
   var args = '';

   // Put rider info in args
   var rds = '';
   var rws = '';
   var rss = '';

   for(var i=0; i<res.numRiders(); i++)
   {
      rds += res.riders[i].id + ';';
      rws += res.riders[i].rweight + ';';
      rss += res.riders[i].sledID + ';';
   }

   args += '&rd=' + rds;
   args += '&rw=' + rws;
   args += '&rs=' + rss;

   // Put sled info in args
   var sds = '';
   var scs = '';

   for(i=0; i<res.numSleds(); i++)
   {
      sds += res.sleds[i].id + ';';
      scs += res.sleds[i].cost + ';';
   }

   args += '&sd=' + sds;
   args += '&sc=' + scs;

   return args;
}

function handleReservation()
{
	if(xmlHttp.readyState == 4)
	{
      var message = '';
		var xmlDoc = xmlHttp.responseXML;
		var r = xmlDoc.getElementsByTagName("result");
      var errorCount = r[0].getAttribute("error") * 1 + 0;

      if(errorCount > 0)
      {
         message = r[0].getAttribute("errorText");
         document.getElementById('confirmResDT').className = 'incomplete';
      }
      else
      {
         res.resID = r[0].getAttribute("resID");
   		// Test if this will work document.getElementById("quantity").value = res.numSleds();

         message = "<h1>Your Reservation has been recorded</h1>";
         message += "<h2>Your reservation ID is: '"+res.resID+"'<br />Your recorded email address is '"+res.email+"'</h2>";
         message += "<p>If you call us to ask about your reservation, we will ask you for this information to confirm your identity.  You may also use your reservation ID and email address to log in and <a href=\"http://www.dogsledrides.com/reservations/check_status.php\">check the status</a> of your reservation.</p>";
         message += "<p>Your reservation is currently pending.  Once we receive payment for your reservation it will be confirmed.  If we do not receive a payment notification within two hours, your reservation will be cancelled and completely removed from the system.</p>";
         message += "<p><button type=\"button\" onclick=\"changeTabByID('pay')\">Move to the next section</button></p>";

         updatePaymentForm();
   		document.getElementById("item_number").value = res.resID;
      }

		document.getElementById("reviewDIV").innerHTML = message;
   }
}

//
//	Add a rider to the rider array
//
function doAddRider()
{
   var riderName = document.getElementById("riderName").value;
   var riderWeight = document.getElementById("riderWeight").value;

   if((riderName == '') || (riderWeight == ''))
      alert("A rider must have both a name and a weight.");
   else
   {
      var riderHeightID = 0;
      var riderHeightText = '';
      var riderAgeID;
      var riderAgeText;

      if(res.type == 'sled')
      {
         riderHeightID = getSelectValue("riderHeight");
         riderHeightText = getSelectText("riderHeight");
         riderAgeID = getSelectValue("riderAge");
         riderAgeText = getSelectText("riderAge");
      }
      else if(res.type == 'cart')
      {
         riderAgeID = getSelectValue("cartRiderAge");
         riderAgeText = getSelectText("cartRiderAge");
      }
      else
      {
         riderAgeID = getSelectValue("scooterRiderAge");
         riderAgeText = getSelectText("scooterRiderAge");
      }

      x = document.getElementById("weightUnits");
      var weightUnits = x.options[x.selectedIndex].value;
      if(weightUnits == 2)
         riderWeight = Math.round(riderWeight * 2.2);
      else if(weightUnits == 3)
         riderWeight = Math.round(riderWeight * 14);
      else
         riderWeight = Math.round(riderWeight * 1);
   
      rider = new riderObj(riderName, riderWeight, riderHeightID, riderHeightText, riderAgeID, riderAgeText);
      res.addRider(rider);

      res.showRiders();
      res.showMatchRiders();

      // Clear name and weight entries and move back to the name field
      document.getElementById("riderWeightLabel").className = 'incomplete';
      document.getElementById("riderNameLabel").className = 'incomplete';
      document.getElementById("riderWeight").value = '';
      document.getElementById("riderName").value = '';
      document.getElementById("riderName").focus();
      resetReview();
   }
}

function doRemoveRider(i)
{
   res.removeRider(i);
   res.showRiders();
   res.showMatchRiders();
   resetReview();
}


function drawPaymentForm()
{
   var txt = '<form action="https://www.paypal.com/cgi-bin/webscr" method="post" id="payPalForm">';
   txt += '<input type="hidden" id="item_number" name="item_number" value="noIDwha" />';
   txt += '<input type="hidden" name="cmd" value="_xclick" />';
   txt += '<input type="hidden" name="no_note" value="1" />';
   txt += '<input type="hidden" name="business" value="winterpark@dogsledrides.com" />';
   txt += '<input type="hidden" name="return" value="http://www.dogsledrides.com/winterpark/reservations/paypal_success.php" />';
   txt += '<input type="hidden" name="cancel_ return" value="http://www.dogsledrides.com/winterpark/reservations/paypal_cancel.php" />';
   txt += '<input type="hidden" name="cbt" value="View further instructions" />';
   txt += '<input type="hidden" name="no_shipping" value="1" />';
   txt += '<input type="hidden" name="rm" value="2" />';
   txt += '<input type="hidden" name="notify_url" value="http://www.dogsledrides.com/winterpark/reservations/paypal_notify.php" />';
   txt += '<input name="item_name" type="hidden" id="item_name"  value="Dog Sled Ride Reservation"><br />';
   txt += '<input id="fullRadio" type="radio" name="amount" value="0" /><label id="fullRadioLabel" for="fullRadio">Pay full amount (0)</label><br />';
   txt += '<input id="halfRadio" type="radio" name="amount" value="0" /><label id="halfRadioLabel" for="halfRadio">Pay 50% deposit (0)</label><br /><br />';
   txt += '<input type="image" src="https://www.paypal.com/en_US/i/btn/btn_buynowCC_LG.gif" border="0" name="submit" alt="">';
   txt += '</form>';

   document.getElementById("payDIV").innerHTML = txt;
}


function updatePaymentForm()
{
   drawPaymentForm();

//   var tot = document.getElementById("totResCost").value * 1;
//   var bal = document.getElementById("balance").value * 1;

   var tot = res.totCost;
   var bal = tot;

//   document.getElementById("item_number").value = document.getElementById("resID").value;
	document.getElementById("item_number").value = res.resID;

   if(bal == tot)
   {
      document.getElementById("fullRadio").value = tot;
      document.getElementById("fullRadio").selected = 'selected';
      document.getElementById("fullRadioLabel").innerHTML = 'Pay full amount ($'+tot+')';
      document.getElementById("halfRadio").value = Math.ceil(tot/2);
      document.getElementById("halfRadioLabel").innerHTML = 'Pay 50% deposit ($'+Math.ceil(tot/2)+')';
   }
   else if(bal == 0)
   {
      document.getElementById("paymentDiv").innerHTML = '<h1>You have a $0 balance, no payment is necessary.</h1>';
   }
   else
   {
      document.getElementById("fullRadio").value = bal;
      document.getElementById("fullRadio").selected = 'selected';
      document.getElementById("fullRadioLabel").innerHTML = 'Pay balance ($'+bal+')';
      document.getElementById("halfRadio").style.display = 'none';
      document.getElementById("halfRadioLabel").style.display = 'none';
   }
}
