﻿/**
 * An object representing a criterion.
 *
 * @param {string} name The name of the criterion.
 * @param {Object} values An object with an boolean entry for each value, or for a single-value
 *     criterion, a string called 'text'.
 * @constructor
 */
function Criterion(name, values) {
  this.name = name;
  this.values = values;
}

var MEDIA_TYPES_ = [
  'Audio Libro',
  'Carpeta',
  'Carta',
  'Casete',
  'CD',
  'CD-ROM',
  'Cuaderno',
  'DVD',
  'Ficha',
  'Fotocopias',
  'Libro',
  'Mapa',
  'Poster',
  'Puzzle',
  'Revista',
  'VHS',
  'Otro'
];

var next_id = 1;
/**
 * Returns the next id to use.
 *
 * @return {number} the next ID to use.
 * @private
 */
function getNextId_() {
  return next_id++;
}

/**
 * Returns html for a single media-type checkbox.
 *
 * @param {string} mediaType The name of the media type.
 * @param {boolean} checked Whether the box is checked.
 * @return {string} HTML for the checkbox.
 */
function getMediaTypeCheckbox(mediaType, checked) {
  var checkbox_id = 'media_type' + getNextId_();
  return ['<nobr><input id="', checkbox_id, '" ',
          'type="checkbox" name="media_type[]" ',
          'value="', mediaType, '"', (checked ? ' checked="checked"' : ''),
          '/>&nbsp;',
          '<label for="', checkbox_id, '">', mediaType, '</label></nobr>'].join('');
}

/**
 * Returns html for all media-type checkboxes
 *
 * @param {string} separator HTML with which to separate the checkboxes.
 * @param {Object} opt_values true/false values for each media type.
 * @return {string} HTML for all checkboxes.
 */
function getMediaTypeCheckboxes(separator, opt_values) {
  var result_html = [];
  for (var i = 0; i < MEDIA_TYPES_.length; ++i) {
    result_html.push(getMediaTypeCheckbox(
        MEDIA_TYPES_[i], 
        (opt_values && opt_values[MEDIA_TYPES_[i]]) ? true : false));
  }
  return result_html.join(separator);
}

/**
 * Changes the display of the value based on the type of criteria.
 *
 * @param {Object} criterionDropdown The dropdown firing the event.
 * @param {string} criterionId the id of the row to change.
 */
function updateCriterionValueField(criterionDropdown, criterionId) {
  var result = getCriterionValueHTML(criterionDropdown.options[criterionDropdown.selectedIndex].value);
  document.getElementById(criterionId).innerHTML = result;
}

/**
 * Returns the HTML for the value field of a criterion.
 *
 * @param {string} name The name of the criterion.
 * @param {Object} opt_values An object with an boolean entry for each value, or for a single-value
 *     criterion, a string called 'text'.
 * @return {string} HTML for the value field.
 */
function getCriterionValueHTML(name, opt_values) {
  if (typeof(opt_values) == 'undefined') {
    opt_values = { text: '' };
  }

  switch (name) {
    case 'author':
    case 'title':
      return [
        '<input type="text" name="', name, '[]" ',
        'size="50" value="', opt_values.text, '"/>'].join('');
      break;
    case 'media_type':
      return (getMediaTypeCheckboxes(' ', opt_values));
  }
}

/**
 * Returns the html for a single criterion box
 *
 * @param {boolean} includeSearchButton Should the search button be included in the last cell
 * @param {Criterion} opt_criterion A criteria to fill the box with.
 * @return {string} HTML for the line in the table.
 */
function getCriterionLine(includeSearchButton, opt_criterion) {
  var criterionId = 'criterionValue' + getNextId_();
  var result_html = [];
  result_html.push(
    '<tr>',
      '<td>',
        '<select name="criterion" onchange="updateCriterionValueField(this, \'' + criterionId + '\')">',
          '<option value="author"', ((opt_criterion != null && opt_criterion.name == 'author') ? ' selected="selected"' : ''), '>Autor</option>',
          '<option value="title"', ((opt_criterion != null && opt_criterion.name == 'title') ? ' selected="selected"' : ''), '>Título</option>',
          '<option value="media_type"', ((opt_criterion != null && opt_criterion.name == 'media_type') ? ' selected="selected"' : ''), '>Formato</option>',
        '</select>',
      '</td>',
      '<td id="', criterionId, '">');
  if (opt_criterion != null) {
    result_html.push(getCriterionValueHTML(opt_criterion.name, opt_criterion.values));
  } else {
    result_html.push(getCriterionValueHTML('author'));
  }

  result_html.push(
      '</td>',
      '<td>',
    (includeSearchButton ? '<input type="submit" value="Buscar Catálogo">' : '&nbsp;'),
      '</td>',
    '</tr>');
  return result_html.join('');
}

/**
 * Writes out a search box into the HTML.
 *
 * @param {string} action The page the search should be sent to.
 * @param {Array.<Criterion>} opt_criteria An array of criteria to fill the search box with.
 */
function addSearchBox(action, opt_criteria) {
  var result_html = [];
  result_html.push(
    '<form method="POST" action="', action, '">',
    '<input type="hidden" name="_submit_check" value="1" />',
    '<table>');
  
  if (opt_criteria != null) {
    for (var i = 0; i < opt_criteria.length; ++i) {
      result_html.push(getCriterionLine(i == opt_criteria.length - 1, opt_criteria[i]));
    }
  } else {
    result_html.push(getCriterionLine(true));
  }

  result_html.push(
      '</table>',
    '</form>'
  );
  document.write(result_html.join('\n'));
}
