// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The list package implements a doubly linked list.
package list

// Element is an element in the linked list.
type Element struct {
	// Next and previous pointers in the doubly-linked list of elements.
	// The front of the list has prev = nil, and the back has next = nil.
	next, prev	*Element;

	// A unique ID for the list to which this element belongs.
	id	*byte;

	// The contents of this list element.
	Value	interface{};
}

// Next returns the next list element or nil.
func (e *Element) Next() *Element {
	return e.next;
}

// Prev returns the previous list element or nil.
func (e *Element) Prev() *Element {
	return e.prev;
}

// List represents a doubly linked list.
type List struct {
	front, back	*Element;
	len		int;
	id		*byte;
}

// Init initializes or clears a List.
func (l *List) Init() *List {
	l.front = nil;
	l.back = nil;
	l.len = 0;
	l.id = new(byte);
	return l;
}

// New returns an initialized list.
func New() *List {
	return new(List).Init();
}

// Front returns the first element in the list.
func (l *List) Front() *Element {
	return l.front;
}

// Back returns the last element in the list.
func (l *List) Back() *Element {
	return l.back;
}

// Remove removes the element from the list.
func (l *List) Remove(e *Element) {
	if e.id != l.id {
		return;
	}
	if e.prev == nil {
		l.front = e.next;
	} else {
		e.prev.next = e.next;
	}
	if e.next == nil {
		l.back = e.prev;
	} else {
		e.next.prev = e.prev;
	}

	e.prev = nil;
	e.next = nil;
	l.len--;
}

func (l *List) insertBefore(e *Element, mark *Element) {
	if mark.prev == nil {
		// new front of the list
		l.front = e;
	} else {
		mark.prev.next = e;
	}
	e.prev = mark.prev;
	mark.prev = e;
	e.next = mark;
	l.len++;
}

func (l *List) insertAfter(e *Element, mark *Element) {
	if mark.next == nil {
		// new back of the list
		l.back = e;
	} else {
		mark.next.prev = e;
	}
	e.next = mark.next;
	mark.next = e;
	e.prev = mark;
	l.len++;
}

func (l *List) insertFront(e *Element) {
	if l.front == nil {
		// empty list
		l.front, l.back = e, e;
		e.prev, e.next = nil, nil;
		l.len = 1;
		return;
	}
	l.insertBefore(e, l.front);
}

func (l *List) insertBack(e *Element) {
	if l.back == nil {
		// empty list
		l.front, l.back = e, e;
		e.prev, e.next = nil, nil;
		l.len = 1;
		return;
	}
	l.insertAfter(e, l.back);
}

// PushFront inserts the value at the front of the list and returns a new Element containing the value.
func (l *List) PushFront(value interface{}) *Element {
	if l.id == nil {
		l.Init();
	}
	e := &Element{nil, nil, l.id, value};
	l.insertFront(e);
	return e;
}

// PushBack inserts the value at the back of the list and returns a new Element containing the value.
func (l *List) PushBack(value interface{}) *Element {
	if l.id == nil {
		l.Init();
	}
	e := &Element{nil, nil, l.id, value};
	l.insertBack(e);
	return e;
}

// InsertBefore inserts the value immediately before mark and returns a new Element containing the value.
func (l *List) InsertBefore(value interface{}, mark *Element) *Element {
	if mark.id != l.id {
		return nil;
	}
	e := &Element{nil, nil, l.id, value};
	l.insertBefore(e, mark);
	return e;
}

// InsertAfter inserts the value immediately after mark and returns a new Element containing the value.
func (l *List) InsertAfter(value interface{}, mark *Element) *Element {
	if mark.id != l.id {
		return nil;
	}
	e := &Element{nil, nil, l.id, value};
	l.insertAfter(e, mark);
	return e;
}

// MoveToFront moves the element to the front of the list.
func (l *List) MoveToFront(e *Element) {
	if e.id != l.id || l.front == e {
		return;
	}
	l.Remove(e);
	l.insertFront(e);
}

// MoveToBack moves the element to the back of the list.
func (l *List) MoveToBack(e *Element) {
	if e.id != l.id || l.back == e {
		return;
	}
	l.Remove(e);
	l.insertBack(e);
}

// Len returns the number of elements in the list.
func (l *List) Len() int {
	return l.len;
}

func (l *List) iterate(c chan<- interface{}) {
	for e := l.front; e != nil; e = e.next {
		c <- e.Value;
	}
	close(c);
}

func (l *List) Iter() <-chan interface{} {
	c := make(chan interface{});
	go l.iterate(c);
	return c;
}
