var DISPLAY_MODE_QUESTION = 1;
var DISPLAY_MODE_ANSWER = 2;


var duration_types = [];

var month_names = ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

function setRadioOnclick (radio, question, option_num) {
  radio.onclick = function () {
    question.selected_value = question.options[option_num].value;
  };
}

/**
* A question
**/
function Question (question, field_name) {
  this.options = [];
  this.question = question;
  this.field_name = field_name;
  this.dom_element = null;
  this.selected_value = null;
  this.display_mode = DISPLAY_MODE_QUESTION;
  this.on_answer = null;
  this.qnum = 0;
  this.on_show = null;
  
  
  /**
  * Draws this question, displays its container DIV and returns the container DIV element
  **/
  this.show = function (elem) {
    //alert ('this.show()\n\nQuestion: ' + this.question);
    
    this.draw();
    this.dom_element.style.display = '';
    
    return this.dom_element;
  };
  
  /**
  * Hides this question
  **/
  this.hide = function () {
    this.dom_element.parentNode.removeChild (this.dom_element);
  };
  
  /**
  * Creates a container for holding the elements.
  * Call before this.show();
  **/
  this.createContainer = function () {
    if (this.dom_element === null) {
      this.dom_element = document.createElement('div');
    }
    
    return this.dom_element;
  }
  
  /**
  * Draws this question. Internal use only.
  **/
  this.draw = function () {
    var p, text, label, radio, hidden, i;
    
    // Remove all children of DIV
    while (this.dom_element.firstChild) {
      this.dom_element.removeChild(this.dom_element.firstChild);
    }
    
    var node = document.createElement ('h4');
    node.appendChild (document.createTextNode (this.question));
    this.dom_element.appendChild (node);
    
    if (this.display_mode == DISPLAY_MODE_QUESTION) {
      // Display the radio buttons
      for (i = 0; i < this.options.length; i++) {
        p = document.createElement ('p');
        text = document.createTextNode (' ' + this.options[i].label);
        label = create_element ('label', {
          'for': 'question_' + this.field_name + '_' + i,
          'style': 'display: inline;'
        });
        radio = create_element ('input', {
          'type': 'radio',
          'name': this.field_name,
          'value': this.options[i].value,
          'id': 'question_' + this.field_name + '_' + i
        });
        
        setRadioOnclick (radio, this, i);
        
        label.appendChild (text);
        p.appendChild (radio);
        p.appendChild (label);
        this.dom_element.appendChild (p);
        
        if (this.selected_value == this.options[i].value) {
          radio.checked = true;
        }
      }
      
      // if there is only one option, select it
      if (this.options.length == 1) {
        radio.checked = true;
        radio.onclick();
      }
      
      
      
    } else if (this.display_mode == DISPLAY_MODE_ANSWER) {
      // Display the currently selected option
      var optn = null;
      for (i = 0; i < this.options.length; i++) {
        if (this.options[i].value == this.selected_value) {
          optn = this.options[i].label;
          break;
        }
      }
      
      p = document.createElement ('p');
      text = document.createTextNode (optn);
      hidden = create_element ('input', {
          'type': 'hidden',
          'name': this.field_name,
          'value': this.selected_value
      });
      
      p.appendChild (hidden);
      p.appendChild (text);
      this.dom_element.appendChild (p);
    }
  };
  
  
  /**
  * Sets the display mode of this question
  * Should be DISPLAY_MODE_QUESTION or DISPLAY_MODE_ANSWER
  **/
  this.setDisplayMode = function (mode) {
    var node;
    
    // Quick validity check
    if (mode == DISPLAY_MODE_ANSWER && this.selected_value === null) {
      if (this.qnum > 1) {
        alert ('Please choose a continent');
      } else {
        alert ('Please answer this question');
      }
      return false;
    }
    
    // Set the mode, and redraw if possible
    this.display_mode = mode;
    if (this.dom_element !== null) {
      this.show(node);
    }
    
    // Fire some hooks
    if (mode == DISPLAY_MODE_ANSWER && this.on_answer !== null) {
      this.on_answer (this, this.selected_value, this.qnum);
    }
    
    if (mode == DISPLAY_MODE_QUESTION && this.on_show !== null) {
      this.on_show (this, this.selected_value, this.qnum);
    }
    
    return true;
  };
  
  /**
  * Adds an option to this question
  **/
  this.addOption = function (option) {
    this.options[this.options.length] = option;
  };
  
  /**
  * Sets a function that should be called when this question is answered
  *
  * function will be called with the forllowing args:
  *   function ( question , selected_value )
  **/
  this.setOnAnswer = function (on_answer) {
    this.on_answer = on_answer;
  };
  
  /**
  * Called whenever a question is shown as an actual question
  **/
  this.setOnShow = function (on_show) {
    this.on_show = on_show;
  };
}


/**
* An option for a question
**/
function QuestionOption (value, label) {
  this.value = value;
  this.label = label;
}


function QuestionList (host) {
  this.questions = [];
  this.num = 0;
  this.host = host;
  
  this.addQuestion = function (question, pos) {
    if (pos == null) pos = this.questions.length;
    question.qnum = pos;
    this.questions[pos] = question;
  };
  
  this.showFirst = function () {
    var node;
    
    node = this.questions[0].createContainer();
    this.host.appendChild (node);
    this.questions[0].show(node);
  };
  
  this.nextQuestion = function () {
    var question;
    var node;
    
    if (this.num >= this.questions.length) { return; }
    
    question = this.questions[this.num];
    if (! question.setDisplayMode(DISPLAY_MODE_ANSWER)) { return; }
    
    this.num++;
    if (this.num >= this.questions.length) { return; }
    
    question = this.questions[this.num];
    if (question === null) { return; }
    
    node = question.createContainer();
    this.host.appendChild (node);
    question.show(node);
  };
  
  this.prevQuestion = function () {
    var question;
    
    if (this.num === 0) { return; }
    
    question = this.questions[this.num];
    if (question !== null) {
      question.setDisplayMode(DISPLAY_MODE_QUESTION);
      question.hide();
    }
    
    this.num--;
    
    question = this.questions[this.num];
    question.setDisplayMode(DISPLAY_MODE_QUESTION);
  };
}




function setAddDestinationOnclick (elem, chooser) {
  elem.onclick = function () {
    chooser.onAddDestination ();
  };
}

function setTransitOnclick (elem, chooser) {
  elem.onclick = function () {
    chooser.onTransit ();
  };
}

function setOwnArrangementOnclick (elem, chooser) {
  elem.onclick = function () {
    chooser.onOwnArrangement ();
  };
}

function setDeleteOnclick (elem, chooser, index, custom) {
  elem.onclick = function () {
    chooser.onDelete (index, custom);
  };
}


function City () {
  this.countryid = null;
  this.cityid = null;
  this.number = null;
  this.numtype = null;
  
  this.checkin_day = null;
  this.checkin_month = null;
  this.checkin_year = null;
  
  this.checkinFromISO8601 = function (date) {
    var sections = date.split('-');
    
    this.checkin_year = sections[0];
    this.checkin_month = sections[1];
    this.checkin_day = sections[2];
  };
}

function day_month_year_onchange (form_name, prefix) {
  document.forms[form_name].elements[prefix + '[d]'].onchange ();
  document.forms[form_name].elements[prefix + '[m]'].onchange ();
  document.forms[form_name].elements[prefix + '[y]'].onchange ();
}

function CityChooser (host) {
  this.host = host;
  this.state = -1;      // -1 = initial, 0 = transit, 0-inf = num of cities
  this.cityelems = [];
  this.continentid = 0;
  
  this.allow_add = 1;
  this.allow_transit = 1;
  this.allow_own = 2;
  this.allow_delete = 1;
  this.allow_arrival = 1;
  this.allow_headings = 1;
  
  
  this.onTransit = function () {
    this.state = 0;
    this.draw();
  };
  
  this.onAddDestination = function () {
    this.addCity (new City (), this.allow_add);
  };
  
  this.onOwnArrangement = function () {
    this.addCity (new City (), this.allow_own);
  };
  
  this.onDelete = function (index, custom) {
    delete (this.cityelems[index]);
    this.state--;
    this.draw(custom);
  };
  
  
  this.setContinentID = function (id) {
    this.continentid = id;
  };
  
  
  /**
  * Adds the specified city
  **/
  this.addCity = function (city, custom) {
    if (this.state == -1) { this.state = 0; }
    
    if (custom == 2) city.arrangement = 1;
    this.cityelems[this.cityelems.length] = city;
    this.state++;
    
    this.draw(custom);
  };
  
  
  /**
  * Appends an <img src="images/clear.gif"> to an element
  **/
  this.appendClear = function (elem) {
    var clear = create_element ('img', {
      'src': 'images/clear.gif',
      'alt': '',
      'class': 'clear'
    });
    elem.appendChild (clear);
  };
  
  
  /**
  * Draws the initial [Transit] or [Add Destination] or [+ Own Arrangements]
  **/
  this.drawInitial = function () {
    var p, span, text, text2, button_transit, button_add, button_own;
    
    if (! this.allow_transit) return;
    
    p = document.createElement ('p');
    text = document.createTextNode ('\u00a0 or \u00a0');
    text2 = document.createTextNode ('\u00a0 or \u00a0');
    
    span = create_element ('span', {
        'style': 'float: right;'
    });
    
    button_transit = create_element ('img', {
        'src': 'images/btn_transit.gif',
        'alt': 'Transit',
        'class': 'buttonroll'
    });
    mlisten ('mouseover', [button_transit], imgon);
    mlisten ('mouseout', [button_transit], imgoff);
    setTransitOnclick (button_transit, this);
    
    button_add = create_element ('img', {
        'src': 'images/btn_add_dest.gif',
        'alt': '+ Add destination',
        'class': 'buttonroll'
    });
    mlisten ('mouseover', [button_add], imgon);
    mlisten ('mouseout', [button_add], imgoff);
    setAddDestinationOnclick (button_add, this);
    
    button_own = create_element ('img', {
      'src': 'images/btn_add_own.gif',
      'alt': '+ Own arrangements',
      'class': 'buttonroll'
    });
    mlisten ('mouseover', [button_own], imgon);
    mlisten ('mouseout', [button_own], imgoff);
    setOwnArrangementOnclick (button_own, this);
    
    if (this.allow_transit) span.appendChild (button_transit);
    if (this.allow_transit || this.allow_add) span.appendChild (text);
    if (this.allow_add) span.appendChild (button_add);
    if (this.allow_transit || this.allow_own) span.appendChild (text2);
    if (this.allow_own) span.appendChild (button_own);
    p.appendChild (span);
    this.host.appendChild (p);
  };
  
  /**
  * Draws the 'In transit...[Add Destination] or [+ Own Arrangements]
  **/
  this.drawTransit = function () {
    var p, span, text, button, button_own;
    
    if (! this.allow_transit) return;
    
    p = document.createElement ('p');
    text = document.createTextNode ('Transit only');
    
    span = create_element ('span', {
        'style': 'float: right;'
    });
    
    button = create_element ('img', {
        'src': 'images/btn_add_dest.gif',
        'alt': '+ Add destination',
        'class': 'buttonroll'
    });
    mlisten ('mouseover', [button], imgon);
    mlisten ('mouseout', [button], imgoff);
    setAddDestinationOnclick (button, this);
    
    button_own = create_element ('img', {
      'src': 'images/btn_add_own.gif',
      'alt': '+ Own arrangements',
      'class': 'buttonroll'
    });
    mlisten ('mouseover', [button_own], imgon);
    mlisten ('mouseout', [button_own], imgoff);
    setOwnArrangementOnclick (button_own, this);
    
    p.appendChild (span);
    if (this.allow_add) span.appendChild (button);
    if (this.allow_add || this.allow_own) span.appendChild (document.createTextNode ('\u00a0 or \u00a0'));
    if (this.allow_own) span.appendChild (button_own);
    p.appendChild (text);
    this.host.appendChild (p);
  };
  
  /**
  * The full kahuna
  **/
  this.drawCities = function (custom) {
    var i, elem, clear;
    
    for (i = 0; i < this.cityelems.length; i++) {
      if (this.cityelems[i] == null) continue;
      
      elem = document.createElement ('div');
      this.host.appendChild (elem);
      
      this.drawCity (elem, this.cityelems[i], i, custom);
    }
  };
  
  /**
  * Draws a single city
  * Returns a node
  **/
  this.drawCity = function (div, city, index, custom) {
    var div, p_buttons, p_location, p_time, p_arrival;
    var text, radio, checkbox, label, select, heading, img;
    var button_dest, button_del, select_country, select_city, select_number;
    var optns, i;
    
    
    // Location heading
    if (this.allow_headings) {
      heading = document.createElement ('h4');
      heading.appendChild (document.createTextNode ('Destination:'));
      div.appendChild (heading);
    } 
    
    if (this.allow_arrangement) {
      p = document.createElement ('p');
      text = document.createTextNode (' Make own arrangement');
      label = create_element ('label', {
        'for': 'arrangement' + '_' + this.continentid + '_' + index,
        'style': 'display: inline;'
      });
      
      checkbox = create_element ('input', {
        'type': 'checkbox',
        'name': 'OwnArrangement' + '_' + this.continentid + '_' + index,
        'value': 1,
        'id': 'arrangement' + '_' + this.continentid + '_' + index
      });
      
      if (checkbox.value == city.arrangement) {
        checkbox.checked = true;
      }
      
      label.appendChild (text);
      p.appendChild (checkbox);
      p.appendChild (label);
      div.appendChild (p);
    }
    
    // Location fields
    p_location = create_element ('p', {});
    div.appendChild (p_location);
    this.appendClear (div);
    
    text = document.createTextNode ('\u00a0');
    
    optns = {};
    optns[city.countryid] = 'Nothing available';
    select_country = create_select ({ name: 'country[' + this.continentid + '][' + index + ']' }, optns, city.countryid);
    
    optns = {};
    optns[city.cityid] = 'Select country first';
    select_city = create_select ({ name: 'city[' + this.continentid + '][' + index + ']' }, optns, city.cityid);
    
    p_location.appendChild (select_country);
    p_location.appendChild (text);
    p_location.appendChild (select_city);
    
    
    // Time heading
    if (this.allow_headings) {
      heading = document.createElement ('h4');
      heading.appendChild (document.createTextNode ('How many days, weeks or months will you stay?'));
      div.appendChild (heading);
    }
    
    
    // Time fields
    p_time = create_element ('p', {});
    div.appendChild (p_time);
    this.appendClear (div);
    
    if (! this.allow_headings) {
      if (custom == 1) {
        text = document.createTextNode ('How long will you stay? \u00a0');
      } else if (custom == 2) {
        text = document.createTextNode ('Own arrangements for how long? \u00a0');
      }
      p_time.appendChild (text);
    }
    
    select_number = create_select (
      { name: 'number[' + this.continentid + '][' + index + ']', style: 'width: 75px' },
      { 0: 'Number', 1: '1', 2: '2', 3: '3', 4: '4', 5: '5', 6: '6', 7: '7', 8: '8', 9: '9', 10: '10' },
      city.number);
    p_time.appendChild (select_number);
    
    text = document.createTextNode ('\u00a0');
    p_time.appendChild (text);
    
    for (i = 1; i < duration_types.length; i++) {
      radio = create_element ('input', {
        'name': 'type[' + this.continentid + '][' + index + ']',
        'value': i,
        'type': 'radio',
        'id': 'type_' + this.continentid + '_' + index + '_' + i
      });
      label = create_element ('label', {'style': 'display: inline;', 'for':'type_' + this.continentid + '_' + index + '_' + i});
      text = document.createTextNode ('\u00a0' + duration_types[i] + '\u00a0');
      
      label.appendChild (text);
      p_time.appendChild (radio);
      p_time.appendChild (label);
      
      radio.onclick = function () {
        city.numtype = this.value;
      };
      
      if (city.numtype == i) {
        radio.checked = true;
      }
    }
    
    
    // Arrival date fields
    if (this.allow_arrival) {
      p_arrival = create_element ('p', { 'class': 'date_select' });
      
      // day
      optns = {};
      optns[0] = 'D';
      for (i = 1; i <= 31; i++) {
        j = new String(i);
        if (j.length < 2) j = '0' + j;
        optns[j] = i;
      }
      select = create_select (
        { name: 'checkin[' + this.continentid + '][' + index + '][d]', style: 'width: 75px' },
        optns,
        city.checkin_day);
      p_arrival.appendChild (select);
      
      select.onchange = function () {
        city.checkin_day = this.value;
      };
      
      p_arrival.appendChild (document.createTextNode ('/'));
      
      // Month
      optns = {};
      optns[0] = 'M';
      for (i = 1; i <= 12; i++) {
        j = new String(i);
        if (j.length < 2) j = '0' + j;
        optns[j] = month_names[i];
      }
      select = create_select (
        { name: 'checkin[' + this.continentid + '][' + index + '][m]', style: 'width: 75px' },
        optns,
        city.checkin_month);
      p_arrival.appendChild (select);
      
      select.onchange = function () {
        city.checkin_month = this.value;
      };
      
      p_arrival.appendChild (document.createTextNode ('/'));
      
      // Year
      optns = {};
      optns[0] = 'Y';
      for (i = new Date().getFullYear(); i <= new Date().getFullYear() + 1; i++) {
        optns[i] = i;
      }
      select = create_select (
        { name: 'checkin[' + this.continentid + '][' + index + '][y]', style: 'width: 75px' },
        optns,
        city.checkin_year);
      p_arrival.appendChild (select);
      
      select.onchange = function () {
        city.checkin_year = this.value;
      };
      
      p_arrival.appendChild (document.createTextNode (' '));
      
      var onclick;
      onclick = "var form_el = find_form (this);";
      onclick += "cal_popup ('/autodev/date_select.php?f=' + form_el.attributes.name.value + '&pre=checkin[" + this.continentid + '][' + index + "]', 'day_month_year_onchange');";
      
      // Calendar icon
      img = create_element ('img', {
          'title': 'Choose date from calendar',
          'alt': '[ Choose date from calendar ]',
          'src': '/autodev/images/calendar.png',
          'onclick': onclick,
          'style': 'cursor: pointer; vertical-align: text-bottom;'
      });
      p_arrival.appendChild (img);
    }
    
    
    // Buttons
    if (this.allow_delete || this.allow_add || this.allow_own) {
      p_buttons = create_element ('p', {
          'style': 'float: right;'
      });
      text = document.createTextNode ('\u00a0 or \u00a0');
      text2 = document.createTextNode ('\u00a0 or \u00a0');
      
      button_del = create_element ('img', {
          'src': 'images/btn_delete.gif',
          'alt': '- Delete',
          'class': 'buttonroll'
      });
      
      mlisten ('mouseover', [button_del], imgon);
      mlisten ('mouseout', [button_del], imgoff);
      setDeleteOnclick (button_del, this, index, custom);
      
      button_dest = create_element ('img', {
          'src': 'images/btn_add_dest.gif',
          'alt': '+ Add destination',
          'class': 'buttonroll'
      });
      
      mlisten ('mouseover', [button_dest], imgon);
      mlisten ('mouseout', [button_dest], imgoff);
      setAddDestinationOnclick (button_dest, this);
      
      button_own = create_element ('img', {
          'src': 'images/btn_add_own.gif',
          'alt': '+ Own arrangements',
          'class': 'buttonroll'
      });
      
      mlisten ('mouseover', [button_own], imgon);
      mlisten ('mouseout', [button_own], imgoff);
      setOwnArrangementOnclick (button_own, this);
      
      if (this.allow_delete) p_buttons.appendChild (button_del);
      if (this.allow_delete && this.allow_add) p_buttons.appendChild (text);
      if (this.allow_add) p_buttons.appendChild (button_dest);
      if (this.allow_add && this.allow_own) p_buttons.appendChild (text2);
      if (this.allow_add && this.allow_own) p_buttons.appendChild (button_own);
    }
    
    
    // Actions
    select_country.onchange = function () {
      city.countryid = this.value;
      
      if (city.countryid == '') {
        select_city.options[0] = new Option('Select country first', '');
        select_city.options.length = 1;
        
      } else {
        var handler = new SelectReplacementHandler (select_city);
        handler.top_option = 'Select city';
        queue.request ('GET', 'ajax_get_cities.php?country=' + this.value, handler);
      }
    };
    
    select_city.onchange = function () {
      city.cityid = this.value;
    };
    
    select_number.onchange = function () {
      city.number = this.value;
    };
    
    
    // Buttons and arrival date
    if (p_arrival && this.allow_headings) {
      heading = document.createElement ('h4');
      heading.appendChild (document.createTextNode ('Check in date:'));
      div.appendChild (heading);
    }
    if (p_buttons) div.appendChild (p_buttons);
    if (p_arrival) div.appendChild (p_arrival);
    this.appendClear (div);
    
    
    // Populate the country list, and the city list if required
    var handler = new SelectReplacementHandler (select_country);
    handler.top_option = 'Select country';
    queue.request ('GET', 'ajax_get_countries.php?continent=' + this.continentid, handler);
    
    if (city.countryid) {
      handler = new SelectReplacementHandler (select_city);
      handler.top_option = 'Select city';
      queue.request ('GET', 'ajax_get_cities.php?country=' + city.countryid, handler);
    }
  };
  
  
  /**
  * Wipes the host
  * Then calls one of drawInitial, drawTransit or drawCities
  * depending on the current state
  **/
  this.draw = function (custom) {
    var clear;
    
    while (this.host.firstChild) {
      this.host.removeChild(this.host.firstChild);
    }
    
    if (this.state == -1) {
      this.drawInitial();
    } else if (this.state === 0) {
      this.drawTransit();
    } else {
      this.drawCities(custom);
    }
    
    this.appendClear (this.host);
  };
  
}
