text: const nodeFrom = value => ({ value, next: null, prev: null });
  
  const add = ( prev, node, next, list ) => {
    if( prev !== null ){
      prev.next = node;
    } else {
      list.head = node;
    }
  
    if( next !== null ){
      next.prev = node;
    } else {
      list.tail = node;
    }
  
    node.prev = prev;
    node.next = next;
  
    list.length++;
  
    return node;
  };
  
  const remove = ( node, list ) => {
    let { prev, next } = node;
  
    if( prev !== null ){
      prev.next = next;
    } else {
      list.head = next;
    }
  
    if( next !== null ){
      next.prev = prev;
    } else {
      list.tail = prev;
    }
  
    node.prev = node.next = null;
  
    list.length--;
  
    return node;
  };
  
  class LinkedList {
    constructor( vals ){
      this.length = 0;
      this.head = null;
      this.tail = null;
  
      if( vals != null ){
        vals.forEach( v => this.push(v) );
      }
    }
  
    size(){
      return this.length;
    }
  
    insertBefore( val, otherNode ){
      return add( otherNode.prev, nodeFrom(val), otherNode, this );
    }
  
    insertAfter( val, otherNode ){
      return add( otherNode, nodeFrom(val), otherNode.next, this );
    }
  
    insertNodeBefore( newNode, otherNode ){
      return add( otherNode.prev, newNode, otherNode, this );
    }
  
    insertNodeAfter( newNode, otherNode ){
      return add( otherNode, newNode, otherNode.next, this );
    }
  
    push( val ){
      return add( this.tail, nodeFrom(val), null, this );
    }
  
    unshift( val ){
      return add( null, nodeFrom(val), this.head, this );
    }
  
    remove( node ){
      return remove( node, this );
    }
  
    pop(){
      return remove( this.tail, this ).value;
    }
  
    popNode(){
       return remove( this.tail, this );
    }
  
    shift(){
      return remove( this.head, this ).value;
    }
  
    shiftNode(){
      return remove( this.head, this );
    }
  
    get_object_at( index ){
      if(index <= this.length()){
        var i = 1;
        var current = this.head;
        while(i < index){
          current = current.next;
          i++;
        }
        return current.value;
      }
    }
  
    set_object_at( index, value){
      if(index <= this.length()) {
        var i = 1;
        var current = this.head;
        while (i < index) {
          current = current.next;
          i++;
        }
        current.value = value;
      }
    }
  }
  
  module.exports = LinkedList;
  