﻿// JScript File

SDLListNode = function()
{
    this._list = null;
    this._prev = null;
    this._next = null;
    this._inserted = false;
}

SDLListNode.prototype.List$ = function(list_)
{
    if(defined(list_))
        this._list = list_;
    else
        return this._list;
}

SDLListNode.prototype.Insert = function(node)
{
    var ele = this.Element$();
    var nEle = node.Element$();
    if(nEle.parentNode != null)
        nEle.parentNode.removeChild(nEle);
    
    if(this._list.Comparer$()(this, node) > 0) { // this > node
        node.NextNode$(this);
        if(this.PrevNode$() != null)
        {
            this.PrevNode$().NextNode$(node);
            node.PrevNode$(this.PrevNode$());
        }
        this.PrevNode$(node);
        
        ele.parentNode.insertBefore(nEle, ele);    
        node._inserted = true;
        
        this._list.UpdateFirstLast();
    } else if(this.NextNode$() == null) { //there is no next node and this <= node
        node.PrevNode$(this);
        this.NextNode$(node);
        
        ele.parentNode.appendChild(nEle);    
        node._inserted = true;
        
        this._list.UpdateFirstLast();
    } else { // this <= node, call insert on the next item since it exists.
        this.NextNode$().Insert(node);
    }
}

SDLListNode.prototype.PrevNode$ = function(node_)
{
    if(defined(node_))
        this._prev = node_;
    else
        return this._prev;
}

SDLListNode.prototype.NextNode$ = function(node_)
{
    if(defined(node_))
        this._next = node_;
    else
        return this._next;
}

SDLListNode.prototype.OnUpdate = function()
{
    if(this._inserted == false)
        return;

    if(this.PrevNode$() == null && this.NextNode$() == null)
        return;
    else if(this.PrevNode$() != null && this._list.Comparer$()(this, this.PrevNode$()) < 0)
    {
        //need to move up the list, start from the top.
        this.PrevNode$().NextNode$(this.NextNode$());
        if(this.NextNode$() != null)
            this.NextNode$().PrevNode$(this.PrevNode$());
        else
            this._list.Last$(this.PrevNode$());
            
        this._inserted = false;
        
        this.PrevNode$(null);
        this.NextNode$(null);
        
        this._list.Add(this);
    }
    else if(this.NextNode$() != null && this._list.Comparer$()(this, this.NextNode$()) > 0)
    {
        //need to move down the list.
        if(this.PrevNode$() != null)
            this.PrevNode$().NextNode$(this.NextNode$());
        else
            this._list.First$(this.NextNode$());
        this.NextNode$().PrevNode$(this.PrevNode$());
        
        var node = this.NextNode$();
        this._inserted = false;
        
        this.PrevNode$(null);
        this.NextNode$(null);
        
        node.Insert(this);
    }
}

SDLList = function(getRootElement_)
{
    this._first = null;
    this._last = null;
    this._comparer = function(a, b) { return 0; }
    if(defined(getRootElement_))
        this._getRootElement = getRootElement_;
    else
        this._getRootElement = function() { return $$("body")[0]; }
}

SDLList.prototype.GetNodeBase = function()
{
    return new SDLListNode(this);
}

SDLList.prototype.RootElement$ = function(fptr_)
{
    if(defined(fptr_))
        this._getRootElement = fptr_;
    else
        return this._getRootElement;
}

SDLList.prototype.ReSort = function()
{
    var nodes = this.toArray();
    this.First$(null);
    this.Last$(null);
    
    for(var i = 0; i < nodes.length; i++)
    {
        nodes[i].PrevNode$(null);
        nodes[i].NextNode$(null);
        nodes[i]._inserted = false;
        this.Add(nodes[i]);
    }
}

//gets or sets a sort comparer.  function(a,b).  if a < b, returns <0, if a > b, returns > 0, if a = b, returns 0;
SDLList.prototype.Comparer$ = function(comparer_)
{
    if(defined(comparer_))
    {
        this._comparer = comparer_;
        this.ReSort();
    }
    else
        return this._comparer;
}

SDLList.prototype.toArray = function()
{
    var ret = [];
    for(var node = this.First$(); node != null; node = node.NextNode$())
        ret.push(node);
    return ret;
}

SDLList.prototype.First$ = function(node_)
{
    if(defined(node_))
        this._first = node_;
    else
        return this._first;
}

SDLList.prototype.Last$ = function(node_)
{
    if(defined(node_))
        this._last = node_;
    else
        return this._last;
}

SDLList.prototype.UpdateFirstLast = function()
{
    if(this.First$() != null)
        while(this.First$().PrevNode$() != null)
            this.First$(this.First$().PrevNode$());
    if(this.Last$() != null)    
        while(this.Last$().NextNode$() != null)
            this.Last$(this.Last$().NextNode$());
}

SDLList.prototype.Add = function(node)
{
    if(this.First$() == null)
    {
        this.First$(node);
        this.Last$(node);
        this.RootElement$()().appendChild(node.Element$());
        node._inserted = true;
    } else
        this.First$().Insert(node);
}





