Thoth.Admin = Thoth.Admin || {};

Thoth.Admin.Name = function () {

// Shorthand.
var d   = document,
    Y   = YAHOO,
    yut = Y.util,
    yuc = yut.Connect,
    yud = yut.Dom,
    yue = yut.Event;

// -- Private Variables ------------------------------------------------------
var conn,
    data,
    delay,
    originalName,
    regexp = /^[0-9a-z_-]+$/i,
    self;

// -- Private Methods --------------------------------------------------------

/**
 * Submits an Ajax request to determine if the current name is valid and not
 * already taken.
 *
 * @method checkName
 * @param {HTMLElement} el name input element
 * @param {String} name name to check
 * @private
 */
function checkName(el, name) {
  if (conn && yuc.isCallInProgress(conn)) {
    yuc.abort(conn);
  }

  var url = '/api/' + (yud.hasClass(el, 'name-post') ? 'post' : 'page') +
      '/check_name?name=' + encodeURIComponent(name);

  conn = yuc.asyncRequest('GET', url, {
    argument: el,
    success : handleCheckResponse,
    timeout : 1000
  });
}

/**
 * Hides the error message associated with the specified name input element.
 *
 * @method hideError
 * @param {HTMLElement} el name input element
 * @private
 */
function hideError(el) {
  var errorEl = yud.get(el.id + '-error');

  if (errorEl) {
    errorEl.parentNode.removeChild(errorEl);
  }
}

/**
 * Shows an error message associated with the specified name input element.
 *
 * @method showError
 * @param {HTMLElement} el name input element
 * @param {String} message error message
 * @private
 */
function showError(el, message) {
  var errorEl = yud.get(el.id + '-error');

  if (!errorEl) {
    errorEl = d.createElement('p');

    errorEl.id        = el.id + '-error';
    errorEl.className = 'flash error';

    yud.insertAfter(errorEl, el);
  }

  errorEl.innerHTML = '';
  errorEl.appendChild(d.createTextNode(message));
}

/**
 * Submits an Ajax request for a name suggestion based on the contents of the
 * specified title input element.
 *
 * @method suggestName
 * @param {HTMLElement} el title input element
 * @param {String} title title string
 * @private
 */
function suggestName(el, title) {
  if (conn && yuc.isCallInProgress(conn)) {
    yuc.abort(conn);
  }

  var url = '/api/' + (yud.hasClass(el, 'title-post') ? 'post' : 'page') +
      '/suggest_name?title=' + encodeURIComponent(title);

  conn = yuc.asyncRequest('GET', url, {
    argument: el,
    success : handleSuggestResponse,
    timeout : 1000
  });
}

// -- Private Event Handlers -------------------------------------------------

/**
 * Handles Ajax check_name responses.
 *
 * @method handleCheckResponse
 * @param {Object} response response object
 * @private
 */
function handleCheckResponse(response) {
  var data

  try {
    data = Y.lang.JSON.parse(response.responseText);
  } catch (e) {
    return;
  }

  if (!data.valid) {
    showError(response.argument, 'Names may only contain letters, numbers, ' +
        'underscores, and dashes, and may not be entirely numeric.');
  } else if (!data.unique && response.argument.value !== originalName) {
    showError(response.argument, 'This name is already taken.');
  } else {
    hideError(response.argument);
  }
}

/**
 * Handles keypress events on name input fields.
 *
 * @method handleKeyPress
 * @param {Event} e event object
 * @private
 */
function handleKeyPress(e) {
  var c  = String.fromCharCode(yue.getCharCode(e)),
      el = yue.getTarget(e);

  if (e.isChar) {
    if (regexp.test(c)) {
      if (/[A-Z]/.test(c)) {
        yue.stopEvent(e);
        el.value += c.toLowerCase();
      }
    } else {
      yue.stopEvent(e);

      if (c === ' ') {
        el.value += '-';
      }
    }
  }
}

/**
 * Handles keyup events on name input fields.
 *
 * @method handleKeyUp
 * @param {Event} e event object
 * @private
 */
function handleKeyUp(e) {
  var el = yue.getTarget(e);

  clearTimeout(delay);

  if (el.value) {
    yue.removeListener('title', 'change', handleTitleChange);

    delay = setTimeout(function () {
      checkName(el, el.value);
    }, 200);
  } else {
    hideError(el);
    yue.on('title', 'change', handleTitleChange, self, true);
  }
}

/**
 * Handles Ajax suggest_name responses.
 *
 * @method handleSuggestResponse
 * @param {Object} response response object
 * @private
 */
function handleSuggestResponse(response) {
  try {
    yud.get('name').value = Y.lang.JSON.parse(response.responseText).name;
  } catch (e) {}
}

/**
 * Handles change events on title input fields.
 *
 * @method handleTitleChange
 * @param {Event} e event object
 * @private
 */
function handleTitleChange(e) {
  var el = yue.getTarget(e);

  if (el.value) {
    suggestName(el, el.value);
  }
}

return {
  // -- Public Methods -------------------------------------------------------

  /**
   * Initializes the Name module on this page.
   *
   * @method init
   */
  init: function () {
    var name = yud.get('name');

    self = this;

    // Listen for keys on name input fields.
    yue.on(name, 'keypress', handleKeyPress, self, true);
    yue.on(name, 'keyup', handleKeyUp, self, true);

    if (!name.value.length) {
      // Listen for changes to title input fields.
      yue.on('title', 'change', handleTitleChange, self, true);
    } else {
      originalName = name.value;
    }
  },
};

}();

YAHOO.util.Event.onContentReady('doc', Thoth.Admin.Name.init, Thoth.Admin.Name,

true);