function LinkedList()
{
  this.length = 0;
  this.startIdx = 0;
  this.endIdx = 0;
  this.seq = 0;
  this.arrData = new Array();

  this.addNode = LinkedList_addNode;
  this.deleteNode = LinkedList_deleteNode;
  this.updateNode = LinkedList_updateNode;
  this.switchNode = LinkedList_switchNode;

  this.getNode = LinkedList_getNode;
  this.getNodeData = LinkedList_getNodeData;
  this.getList = LinkedList_getList;
}

function LinkedList_addNode(data, insertIdxAtNext)
{
  ++this.seq;
  var objNode = new LinkedListData(this.seq, data);
  this.arrData[this.seq] = objNode;

  if (this.startIdx == 0)
  {
    this.startIdx = this.seq;
    this.endIdx = this.seq;
  }
  else
  {
    if (insertIdxAtNext && this.arrData[insertIdxAtNext] && this.arrData[insertIdxAtNext].keyIdx != this.seq)
    {
      objNode.prevIdx = insertIdxAtNext;

      if (this.arrData[insertIdxAtNext].nextIdx)
      {
        objNode.nextIdx = this.arrData[insertIdxAtNext].nextIdx;
        this.arrData[this.arrData[insertIdxAtNext].nextIdx].prevIdx = this.seq;
      }

      this.arrData[insertIdxAtNext].nextIdx = this.seq;

      if (insertIdxAtNext == this.endIdx)
        this.endIdx = this.seq;
    }
    else if (insertIdxAtNext == 0)
    {
      objNode.nextIdx = this.startIdx;
      this.arrData[this.startIdx].prevIdx = this.seq;
      this.startIdx = this.seq;
    }
    else
    {
      this.arrData[this.endIdx].nextIdx = this.seq;
      objNode.prevIdx = this.endIdx;
      this.endIdx = this.seq;
    }
  }

  this.length++;
}

function LinkedList_deleteNode(keyIdx)
{
  if (this.length <= 0 || keyIdx <= 0) return;

  if (typeof(this.arrData[keyIdx]) == "object")
  {
    if (this.startIdx == keyIdx) // Ã³À½ À§Ä¡ »èÁ¦
    {
      this.startIdx = this.arrData[keyIdx].nextIdx;
      if (this.startIdx > 0)
        this.arrData[this.startIdx].prevIdx = 0;
      else
        this.endIdx = 0;
    }
    else if (this.endIdx == keyIdx) // ¸¶Áö¸· À§Ä¡ »èÁ¦
    {
      this.endIdx = this.arrData[keyIdx].prevIdx;
      this.arrData[this.endIdx].nextIdx = 0;
    }
    else // Áß°£
    {
      var tmpPrevIdx = this.arrData[keyIdx].prevIdx;
      var tmpNextIdx = this.arrData[keyIdx].nextIdx;
      this.arrData[tmpNextIdx].prevIdx = tmpPrevIdx;
      this.arrData[tmpPrevIdx].nextIdx = tmpNextIdx;
    }

    delete this.arrData[keyIdx];
    this.length--;
  }
  else
  {
    //alert('not found data for delete'); // DEBUG
  }
}

function LinkedList_updateNode(keyIdx, data)
{
  if (this.arrData[keyIdx])
    this.arrData[keyIdx].data = data;
}

function LinkedList_switchNode(keyIdx1, keyIdx2)
{
  var prevIdx1, prevIdx2;
  var nextIdx1, nextIdx2;
  var tmpIdx;

  if (!this.arrData[keyIdx1] || !this.arrData[keyIdx2])
    return;
  if (keyIdx1 == keyIdx2)
    return;

  if (this.arrData[keyIdx1].prevIdx == keyIdx2) // ±ÙÁ¢ linked list ¼ø¼­ Á¶Á¤
  {
    tmpIdx = keyIdx1;
    keyIdx1 = keyIdx2;
    keyIdx2 = tmpIdx;
  }

  prevIdx1 = this.arrData[keyIdx1].prevIdx;
  prevIdx2 = this.arrData[keyIdx2].prevIdx;
  nextIdx1 = this.arrData[keyIdx1].nextIdx;
  nextIdx2 = this.arrData[keyIdx2].nextIdx;

  if (this.arrData[keyIdx2].nextIdx)
    this.arrData[this.arrData[keyIdx2].nextIdx].prevIdx = keyIdx1;
  if (this.arrData[keyIdx1].prevIdx)
    this.arrData[this.arrData[keyIdx1].prevIdx].nextIdx = keyIdx2;
 
  if (this.arrData[keyIdx1].nextIdx == keyIdx2)
  {
    this.arrData[keyIdx1].prevIdx = keyIdx2;
    this.arrData[keyIdx1].nextIdx = nextIdx2;
    this.arrData[keyIdx2].prevIdx = prevIdx1;
    this.arrData[keyIdx2].nextIdx = keyIdx1;
  }
  else
  {
    if (this.arrData[keyIdx1].nextIdx)
      this.arrData[this.arrData[keyIdx1].nextIdx].prevIdx = keyIdx2;
    if (this.arrData[keyIdx2].prevIdx)
      this.arrData[this.arrData[keyIdx2].prevIdx].nextIdx = keyIdx1;

    this.arrData[keyIdx1].prevIdx = prevIdx2;
    this.arrData[keyIdx2].prevIdx = prevIdx1;
    this.arrData[keyIdx1].nextIdx = nextIdx2;
    this.arrData[keyIdx2].nextIdx = nextIdx1;
  }

  if (this.startIdx == keyIdx1)
    this.startIdx = keyIdx2;
  else if (this.startIdx == keyIdx2)
    this.startIdx = keyIdx1;

  if (this.endIdx == keyIdx1)
    this.endIdx = keyIdx2;
  else if (this.endIdx == keyIdx2)
    this.endIdx = keyIdx1;
}

function LinkedList_getNode(keyIdx)
{
  if (this.arrData[keyIdx])
    return this.arrData[keyIdx];
  else
    return '';
}

function LinkedList_getNodeData(keyIdx)
{
  if (this.arrData[keyIdx] && this.arrData[keyIdx].data)
    return this.arrData[keyIdx].data;
  else
    return '';
}

function LinkedList_getList()
{
  var arrRetData = new Array();
  var i, curIdx;
  var strDebugMsg = ''; // DEBUG

  if (this.length == 0 || this.startIdx == 0)
    return arrRetData;

  curIdx = this.startIdx;
  while (curIdx > 0)
  {
    //strDebugMsg += '\n'+(this.arrData[curIdx].prevIdx+'<'+this.arrData[curIdx].keyIdx+'>'+this.arrData[curIdx].nextIdx); // DEBUG 

    arrRetData[arrRetData.length] = this.arrData[curIdx];
    curIdx = this.arrData[curIdx].nextIdx;
  }

  //alert(strDebugMsg); // DEBUG

  return arrRetData;
}

function LinkedListData(keyIdx, data)
{
  this.keyIdx = keyIdx;
  this.data = data;

  this.prevIdx = 0;
  this.nextIdx = 0;
}

