/**
 * Copyright (C) 2007  Red Hat
 * see file 'COPYING' for use and warranty information
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; version 2 only
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

/**
 * dynamicedit.js
 *
 * Shared code, data, and functions for the dynamic add/remove lists on the
 * edit group/user pages.
 *
 * These functions have specific expectations of the page they are used on:
 *
 * - If you want to preserve the dn_to_info_hash on round trip:
 *     - The form must have a 'form_dn_to_info_json' hidden field.
 *     - The form must have onsubmit="preSubmit()" set in its tag.
 *     - Restoring the contents of add/remove lists on round trip unfortunately
 *       can't be shared because it is a mixture of python and javascript.  See
 *       the bottom part editgroup.kid for example code on this.
 *
 * - The page must have a div: 'newmembers'
 *   that new members are dynamically added to.
 *
 * - The page must have a div: 'delmembers'
 *   that removed members are dynamically added to.
 *
 * - Hidden fields called 'dnadd' and 'dndel' will be dynamically created,
 *   holding the values of the 'dn' passed to addmember() and removemember()
 *
 * Other Notes:
 *
 * - Many of the fields refer to 'dn'.  There is no intrinsic reason this has
 *   to be a dn (it can hold any "unique id" for the objects to add/remove)
 *
 * - Similarly, the word 'member' is used because the code was originally
 *   written for editgroup.  A 'member' is just a 'thing' to add/remove.
 *   On the useredit pages, for example, a 'member' is actually a group.
 */

// Stored as the values in the dn_to_info_hash
MemberDisplayInfo = Class.create();
MemberDisplayInfo.prototype = {
  initialize: function(name, descr, type) {
    this.name = name;
    this.descr = descr;
    this.type = type;
  }
};


// this is used for round-trip recontruction of the names.
// the hidden fields only contain dns.
var dn_to_info_hash = new Hash();

// used to filter search results.
// records dns already in the group
var member_hash = new Hash();

// used to prevent double adding
// records dns to be added
var added_hash = new Hash();

// Tracks the div ids that each member belongs to.
// Since dn's will contain illegal characters for div ids, this is used
// to map them to the correct div
var dn_to_member_div_id = new Hash();



/*
 * Renders the information about the member into the passed in
 * element.  This is used by addmember and removemember to
 * consistently create the dom for the member information
 * (name, descr) and add icons/font changes correct for each type.
 */
function renderMemberInfo(newdiv, info) {
  if (info.type == "user") {
    bold = document.createElement('b');
    bold.appendChild(document.createTextNode(
      info.name + " " + info.descr + " "));
    newdiv.appendChild(bold);
  } else if (info.type == "iuser") {
    newdiv.appendChild(document.createTextNode(
      info.name + " " + info.descr + " "));
  } else if (info.type == "group") {
    ital = document.createElement('i');
    bold = document.createElement('b');
    ital.appendChild(bold);
    bold.appendChild(document.createTextNode(
      info.name + " " + 
      info.descr + " "));
    newdiv.appendChild(ital);
  } else if (info.type == "igroup") {
    ital = document.createElement('i');
    ital.appendChild(document.createTextNode(
      info.name + " " + 
      info.descr + " "));
    newdiv.appendChild(ital);
  }
}

/*
 * Callback used for afterFinish in scriptaculous effect
 */
function removeElement(effect) {
  Element.remove(effect.element);
}

function addmember(dn, info) {
  dn_to_info_hash[dn] = info;

  if ((added_hash[dn] == 1) || (member_hash[dn] == 1)) {
    return null;
  }
  added_hash[dn] = 1;

  var newdiv = document.createElement('div');
  renderMemberInfo(newdiv, info);

  var undolink = document.createElement('a');
  undolink.setAttribute('href', '');
  undolink.setAttribute('onclick',
    'new Effect.Fade(Element.up(this), {afterFinish: removeElement, duration: 0.75});' +
    'added_hash.remove("' + jsStringEscape(dn) + '");' +
    'return false;');
  undolink.appendChild(document.createTextNode("undo"));
  newdiv.appendChild(undolink);

  var dnInfo = document.createElement('input');
  dnInfo.setAttribute('type', 'hidden');
  dnInfo.setAttribute('name', 'dnadd');
  dnInfo.setAttribute('value', dn);
  newdiv.appendChild(dnInfo);

  newdiv.style.display = 'none';
  $('newmembers').appendChild(newdiv);

  return newdiv;
}

function addmemberHandler(element, dn, info) {
  var newdiv = addmember(dn, info);
  if (newdiv != null) {
    new Effect.Fade(Element.up(element), {duration: 0.75});
    new Effect.Appear(newdiv, {duration: 0.75});
    /* Element.up(element).remove(); */
  }
}

function removemember(dn, info) {
  dn_to_info_hash[dn] = info;

  var newdiv = document.createElement('div');
  renderMemberInfo(newdiv, info);

  orig_div_id = dn_to_member_div_id[dn];
  var undolink = document.createElement('a');
  undolink.setAttribute('href', '');
  undolink.setAttribute('onclick',
    'new Effect.Fade(Element.up(this), {afterFinish: removeElement, duration: 0.75});' +
    "new Effect.Appear($('" + orig_div_id + "'), {duration: 0.75});" +
    'return false;');
  undolink.appendChild(document.createTextNode("undo"));
  newdiv.appendChild(undolink);

  var dnInfo = document.createElement('input');
  dnInfo.setAttribute('type', 'hidden');
  dnInfo.setAttribute('name', 'dndel');
  dnInfo.setAttribute('value', dn);
  newdiv.appendChild(dnInfo);

  newdiv.style.display = 'none';
  $('delmembers').appendChild(newdiv);

  return newdiv;
}

function removememberHandler(element, dn, info) {
  var newdiv = removemember(dn, info);
  new Effect.Fade(Element.up(element), {duration: 0.75});
  new Effect.Appear(newdiv, {duration: 0.75});
  /* Element.up(element).remove(); */
}

function preSubmit() {
  var json = dn_to_info_hash.toJSON();
  $('form_dn_to_info_json').value = json;
  return true;
}

function enterDoSearch(e) {
  var keyPressed;
  if (window.event) {
    keyPressed = window.event.keyCode;
  } else {
    keyPressed = e.which; 
  }

  if (keyPressed == 13) {
    return doSearch();
  } else {
    return true;
  }
}
