/**
 * @fileOverview Kapitola 7 – skript příkladu Hudební knihovna.
 * V tomto skriptu se nachází komentáře ve formátu dokumentačních bloků
 * nástroje JsDoc Toolkit.
 * Oficiální stránky projektu JsDoc Toolkit jsou k dispozici na adrese
 * http://code.google.com/p/jsdoc-toolkit/.
 * @author Ondřej Baše
 */

/**
 * Upozornění na duplicitní položku v seznamu skladeb.
 * @constant
 */
var UPOZORNENI_NA_DUPLICITNI_POLOZKU =
  'Právě jste vložil/a skladbu, kterou už ve svém seznamu skladeb máte.',

  /**
   * Předpona identifikátoru skladby.
   * @constant
   */
  PREDPONA_IDENTIFIKATORU_SKLADBY = 'skladba-',

  /**
   * Pole s vybranými skladami. Klíče jsou identifikátory skladeb
   * a jedinou možnou hodnotou je pravdivostní hodnota true.
   * @type {Array}
   */
  vybraneSkladby = [];

$(inicializujSkript);

/**
 * Inicializuje skript. Tato funkce se volá, když webový prohlížeč načte model
 * DOM. Uvnitř ní především svazujeme události s elementy a obsluhujícími
 * funkcemi, a také inicializujeme interakce knihovny jQuery UI.
 */
function inicializujSkript() {
  $('#hudebni-knihovna li, #seznam-skladeb li')
    .wrapInner('<div class="nazev ui-corner-all"></div>')
    .prepend('<div class="odrazka"></div>')
    .addClass('ui-helper-clearfix');

  $('#hudebni-knihovna li').draggable({
    helper: 'clone',
    handle: '.odrazka',
    connectToSortable: '#seznam-skladeb',
    revert: 'invalid'
  });

  var nastaveniSelectable = {
    filter: 'li',
    selected: vyberSkladbu,
    unselected: zrusVyberSkladby
  };

  $('#seznam-skladeb')
    .sortable({
      handle: '.odrazka',
      revert: true,
      receive: uzivatelPridalNovouPolozku
    })
    .selectable(nastaveniSelectable);

  $('#hudebni-knihovna')
    .selectable(nastaveniSelectable);

  $('#oznac-jako-oblibene').click(oznacVybraneSkladbyJakoOblibene);
  $('#vyrad-z-oblibenych').click(vyradVybraneSkladbyZOblibenych);
};

/**
 * Obsluhující funkce pro událost receive interakce Sortable, která vzniká na
 * elementu s identifikátorem seznam-skladeb. Měli bychom zobrazit upozornění
 * v případě, že uživatel přidal do seznamu skladeb položku, která už se v něm
 * nachází.
 * @param {Object} ev Objekt události.
 * @param {Object} ui Objekt ui pro událost receive interakce Sortable.
 */
function uzivatelPridalNovouPolozku(ev, ui) {
  if (pocetStejnychPolozek(ui.item) > 1) {
    window.alert(UPOZORNENI_NA_DUPLICITNI_POLOZKU);
  }
}

/**
 * Zjištuje, kolik položek odpovídajících zadané položce lze najít v seznamu
 * skladeb.
 * @param {Object} $polozka Objekt knihovny jQuery obsahující položku seznamu.
 * @returns {Number} Počet stejných položek.
 */
function pocetStejnychPolozek($polozka) {
  var $shodujiciSePolozky =
    $('#seznam-skladeb li.' + PREDPONA_IDENTIFIKATORU_SKLADBY +
      urciIdSkladby($polozka));

  return $shodujiciSePolozky.length;
}

/**
 * Určuje identifikátor skladby z položky seznamu.
 * @param {Object} $polozka Objekt knihovny jQuery obsahující položku seznamu.
 * @returns {Number} Identifikátor skladby.
 */
function urciIdSkladby($polozka) {
  var hodnotaAtributuClass = $polozka.attr('class'),
    vysledkyHledani = hodnotaAtributuClass.match(
      new RegExp(PREDPONA_IDENTIFIKATORU_SKLADBY + '([0-9]+)'));

  return parseInt(vysledkyHledani[1]);
}

/**
 * Obsluhující funkce pro událost selected interakce Selectable, jež se spouští
 * na elementech s identifikátory hudebni-knihovna a seznam-skladeb. Ukládáme
 * identifikátor vybrané skladby do globální proměnné {@link vybraneSkladby}.
 * Kromě toho nastavujeme všechny odpovídající položky jako vybrané.
 * @param {Object} ev Objekt události.
 * @param {Object} ui Objekt ui pro událost selected interakce Selectable.
 */
function vyberSkladbu(ev, ui) {
  var idSkladby = urciIdSkladby($(ui.selected));

  vybraneSkladby[idSkladby] = true;

  vratOdpovidajiciPolozky(idSkladby).addClass('ui-selected');
}

/**
 * Vrátí objekt knihovny jQuery, jenž obsahuje všechny položky seznamu
 * s uvedeným identifikátorem skladby, a to ze seznamů s identifikátory
 * hudebni-knihovna a seznam-skladeb.
 * @param {Number} idSkladby Identifikátor skladby.
 * @returns {Object} Objekt knihovny jQuery obalující příslušné položky.
 */
function vratOdpovidajiciPolozky(idSkladby) {
  var trida = PREDPONA_IDENTIFIKATORU_SKLADBY + idSkladby;

  return $('#hudebni-knihovna li.' + trida +
    ', #seznam-skladeb li.' + trida);
}

/**
 * Obsluhující funkce pro událost unselected interakce Selectable, která vzniká
 * na elementech s identifikátory hudebni-knihovna a seznam-skladeb.
 * Odstraňujeme identifikátor příslušné skladby z globální proměnné
 * {@link vybraneSkladby}. Kromě toho rušíme výběr všech odpovídajících
 * položek.
 * @param {Object} ev Objekt události.
 * @param {Object} ui Objekt ui pro událost unselected interakce Selectable.
 */
function zrusVyberSkladby(ev, ui) {
  var idSkladby = urciIdSkladby($(ui.unselected));

  delete vybraneSkladby[idSkladby];

  vratOdpovidajiciPolozky(idSkladby).removeClass('ui-selected');
}

/**
 * Označuje všechny vybrané skladby uložené v globální proměnné
 * {@link vybraneSkladby} jako oblíbené.
 * @returns {Boolean} Hodnota false, s níž rušíme výchozí akci prohlížeče.
 */
function oznacVybraneSkladbyJakoOblibene() {
  for (var idSkladby in vybraneSkladby) {
    vratOdpovidajiciPolozky(idSkladby).addClass('oblibena-skladba');
  }

  return false;
}

/**
 * Vyřazuje všechny vybrané skladby uložené v globální proměnné
 * {@link vybraneSkladby} z oblíbených skladeb.
 * @returns {Boolean} Hodnota false, s níž rušíme výchozí akci prohlížeče.
 */
function vyradVybraneSkladbyZOblibenych() {
  for (var idSkladby in vybraneSkladby) {
    vratOdpovidajiciPolozky(idSkladby).removeClass('oblibena-skladba');
  }

  return false;
}