/* uiTree
 * asynchroniously get data from PHP, AJAX and work with
 * by JSON
 * autor @ Miroslav Kovar
 * developed for Pilot.cz
 * usage:
 
 new uiTree({
   url: '/modules/ftp/tree/tree.php',
   container: $$('#tree .a')[0],
   keyboard: true,
   checked: true,
   lock: [
     '/img/e-shop/obrazek-1',
     '/img/e-shop/obrazek-2',
     '/img/e-shop/obrazek-3',
     '/flash'
   ],
   select: function()
   {    
     // getters:
     // this.node return informations of node all attrbutes form ajax request
     // this.line return <li> from DOM
     // this.parent return <ul> from DOM
     // alert(this.node.url);
   },
   dblclick: function(event)
   {
     new Event(event).stop(); // because of duplicating event in DOM model     
     // getters:
     // this.node return informations of node all attrbutes form ajax request
     // this.line return <li> from DOM
     // this.parent return <ul> from DOM
     
     alert(this.node.url);
   }
 });
 */
var tree = new Class({
  Implements: Options,

  options: {
    keyboard: false,
    blankImg: '/css/global/ui/img/tree/blank.gif',
    container: new Element('div', {'class': 'tree'}).empty(),
    lock: [],
    change: new Function(),
    click: new Function(),
    select: new Function(),
    dblclick: new Function(),
    path: '',
    found: false,
    label: false,
    drag: false
  },
  
  initialize: function(options){
    this.setOptions(options);
    
    // console.log('tree: '+this.options.url);
    
    // first init
    if (!this.options.parent)
    {
      this.options.urlBase   = this.options.url;
      this.firstinit = true;
      this.options.parent = this.options.container;
      this.options.parent.empty();
      
      if (this.options.refresh_event)
      {
        document.addEvent(this.options.refresh_event, this.refresh.bind(this.options));
      }
    }
    
    this.ajax();

    if (this.options.keyboard)
    {
      // alert('turning onf keyboard driver');
      this.keyboard_control();
      this.options.keyboard = false;
    }

    return this.options.container;
  },
  ajax: function(){
    // console.log(this.options.url);
  		new ajax('json', {
  		  url: this.options.url,
        // method: 'get',
        onRequest: this.ajax_request.bind(this),
        // onComplete: this.ajax_success.bind(this),
        onComplete: this.ajax_success.bind(this),
        onFailure: this.ajax_failure.bind(this),
        autoCancel: true
  		}).get();		
  },
  ajax_request: function(){
    if (this.options.container.get('tag') == 'li')
    {
      this.oldClass = this.options.container.getProperty('class');
      this.options.container.setProperty('class', 'loading');
    }
  },
  ajax_failure: function(){
    alert('no internet connection...');
  },
  ajax_success: function(get){
    document.fireEvent('tree_loaded_success');
    if (this.options.container.get('tag') == 'li')
    {
      this.options.container.setProperty('class', this.oldClass);
    }
    var running = false;
    if (running !== true)
    {
      // var get = Json.evaluate(response);
      if (!get)
      {
        // this.options.container.getElement('.arrow').removeClass('fo');
        this.options.container.setProperty('class', 'empty');
        this.options.container.fireEvent('k_click');
        this.options.container.fireEvent('k_click_up');
      }
      else {
        var ul = new Element('ul');
        
        if (this.firstinit)
        {
          ul.addClass('uiTree');
          if (Browser.Engine.trident4){ul.addClass('ie6');}
          if (Browser.Engine.trident5){ul.addClass('ie7');}
          if (Browser.Engine.gecko){ul.addClass('gecko');}
          if (Browser.Engine.webkit){ul.addClass('webkit');}
          if (Browser.Engine.presto){ul.addClass('opera');}          
        }
        var lf = (get[0].url.split('/').length-2)*10;
        $each(get, function(node, index)
        {
          // node.cls,
          // node.text
          // node.url
          // node.xxxx
        
          var li  = new Element('li', {
            'class': node.cls+' node',
            'title': node.text,
            'draggable': this.options.draggable,
            'dropable': this.options.draggable,
            'events': {
              mouseenter: function() {
                this.addClass('hover');
              },
              mouseleave: function() {
                this.removeClass('hover');
              },
              click: function(e){
                new Event(e).stop();
              }
            },
            'styles': {
              // 'padding-left': lf,
              'background-position': (lf+18)+'px 0px'
            }
          });
          
          if (this.options.drag) {
            this.options.drag(li);
          }
                    
          if (this.options.label)
          {
            li.set('html', node.text+'<span></span>');
          }
          else {
            li.set('text', node.text);
          }
          
          // lock
          if (this.options.lock.contains(node.url) || node.lock == true)
          {
            li.setProperty('class', 'lock');
          }
          
          node.path = this.options.path+'/'+node.text;
          li.addEvent('dblclick', this.options.dblclick.bindWithEvent({'line': li, 'parent': ul, 'node': node}));
          li.addEvent('select', this.options.select.bindWithEvent({'line': li, 'parent': ul, 'node': node}));
          li.addEvent('click', function(tree, li, node)
          {
            $$('.uiTree li').removeClass('selected');
          
            li.addClass('selected');
            li.fireEvent('select');
          }.pass([this, li, node]));
        
          // difrenet name of Event, because of FFox bug
          li.addEvent('k_click', function(tree, li, node)
          {
            tree.options.parent.getElements('li').removeClass('selected');
            li.addClass('selected');
            // li.fireEvent('select');
          }.pass([this, li, node]));
        
          // difrenet name of Event, because of FFox bug
          li.addEvent('k_click_up', function(tree, li, node)
          {
            li.fireEvent('select');
          }.pass([this, li, node]));
          
          // checked
          if (this.options.check)
          {
            check = new Element('img', {
              'src': this.options.blankImg, 
              'class': 'check',
              'events': {
                'click': function()
                {
                  this.toggleClass('checked');
                },
                'dblclick': function(e){new Event(e).stop();}
              }
            });
            check.injectTop(li);
          }
          
          if (node.cls.test('folder') && !(this.options.lock.contains(node.url) || node.lock == true))
          {
            // var arrow = new Element('img', {
            //   'src': this.options.blankImg,
            //   'class': 'arrow fo',
            //   'styles': {
            //     'margin-left': lf
            //   },
            //   'events': {
            //     'dblclick': function(e) {new Event(e).stop();},
            //     'click': function(e) {new Event(e).stop();}
            //   }
            // });
            
            var arrow = new Element('ins', {
              'class': 'arrow fo',
              'styles': {
                'margin-left': lf
              },
              'events': {
                'dblclick': function(e) {new Event(e).stop();},
                'click': function(e) {new Event(e).stop();}
              }
            });
          
            arrow.addEvent('click',   this.node_open.pass([this, li, node]));  // folder click to open node
            arrow.addEvent('k_click', this.node_open.pass([this, li, node]));  // folder click to open node
            arrow.injectTop(li);
            
            if (this.options.find)
            {
              var uri = '';
              uri = node.url;
                            
              if (this.options.find.contains(uri, '/') && uri !== this.options.find)
              {
                arrow.addClass('findme');
              }
            }
          }
          else {
           // var img = new Element('img', {
           //    'src': this.options.blankImg,
           //    'class': 'arrow',
           //    'styles': {
           //      'margin-left': lf
           //    }
           //  }).injectTop(li);
           var img = new Element('ins', {
              'class': 'arrow',
              'styles': {
                'margin-left': lf
              }
            }).injectTop(li);
          }
          
          
          if (this.options.find)
          {
            if (node)
            {
              this.options.found = false;
              if (node.url+'/' == this.options.find)
              {                
                // li.addClass('findme');
                li.addClass('selected');
                this.options.found = true;
              }
            }
          }
          
          li.injectInside(ul);          
        }.bind(this));
               
        // show
    		this.insert(ul);
    	}
  	}
  },
  insert: function(ul){
		ul.inject(this.options.container);		
    var ulHeight = ul.getSize().y;
    
    this.options.change();
    
    ul.setStyles({'height': 0, 'overflow': 'hidden'});

    new Fx.Tween(ul, {
      duration: 200,
      onComplete: function(ul)
      {
        if (Browser.Engine.trident4)
        {
          ul.setStyles({'overflow': ''});
        }
        else {
          ul.setStyles({'height': 'auto', 'overflow': ''});
        }
        
        if (this.options.found)
        {
          (function(ul){
            new Fx.Scroll(this.options.container.getParent('.bd'), {
              onComplete: function()
              {
                this.options.change();
              }.bind(this)
            }).toElement(ul.getLast('li.selected'));
          
          }).delay(1, this, ul);
        }
      }.bind(this, ul)
    }).start('height', 0, ulHeight);
      
    
    if (ul.getElement('.findme'))
    {
      (function(){
        this.fireEvent('k_click');
        // this.setStyle('background', 'red');
      }).delay(1, ul.getElement('.arrow.findme'));
      
      // ul.getLast('li.findme').setStyle('background', 'blue');  
    }
  },
  node_open: function(thisTree, li, node){
    // open only folders
    if (node.cls.test('folder'))
    {
      // dont have any child
      if (!li.getElement('ul'))
      {    
        li.addClass('open');        
        li.getElement('.arrow').addClass('open');
        var newTree = thisTree.options;
            newTree.container = li;
            newTree.urlBase = thisTree.options.urlBase;
            if (thisTree.options.urlBase.test(/\?/))
            {
              newTree.url = thisTree.options.urlBase+'&node='+node.url;
            }
            else {
              newTree.url = thisTree.options.urlBase+'?node='+node.url;
            }      
            newTree.path = node.path;
            
        // console.log(newTree.path);
            
        new tree(newTree);
      }
      // already opened
      else {
        thisTree.show_hide.attempt([li, node], thisTree);
      }
    }
  },
  show_hide: function(li, node){
    // hide
    if (li.hasClass('open'))
    {
      li.removeClass('open');
      li.getElement('.arrow').removeClass('open');
      var ul = li.getElement('ul');
      
      new Fx.Tween(ul, {
        duration: 200,
        transition: Fx.Transitions.linear,
        onStart: function()
        {
          this.setStyle('overflow', 'hidden');
        }.bind(ul),
        onComplete: this.options.change
        }).start('height', ul.getSize().y, 0);
    }
    // show
    else {
      // this.options.change();
      li.addClass('open');
      li.getElement('.arrow').addClass('open');
      var ul = li.getElement('ul');
      
      new Fx.Tween(ul, {
        duration: 200,
        transition: Fx.Transitions.linear,
        onStart: function()
        {
          this.setStyle('overflow', 'hidden');
        }.bind(ul),
        onComplete: function(obj)
        {
          if (Browser.Engine.trident4)
          {
            this.setStyles({'overflow': '' });
          }
          else {
            this.setStyles({'overflow': '', 'height': 'auto'});
          }
          obj.options.change();
        }.bind(ul, this)
      }).start('height', 0, ul.getScrollSize().y);
    }
  },
  keyboard_control: function(){ 
    this.options.panel.addEvent('keyup', function(event)
    {
      var event = new Event(event);
      if (event.key == 'down' || event.key == 'up' || event.key == 'left' || event.key == 'right')
      {
        new Event(event).stop();
        var li = this.options.parent.getElement('li.selected');
        
        
        // fire::select
        if (li)
        {
          if (event.key == 'down' || event.key == 'up')
          {
            li.fireEvent('k_click');         
          }
        }
      }
    }.bind(this));
    
    // alert('keyboard control on');
    this.options.panel.addEvent('keydown', function(event)
    {
      var event = new Event(event);
      // event.preventDefault();
      if (event.key == 'down' || event.key == 'up' || event.key == 'left' || event.key == 'right')
      {
        new Event(event).stop();      
        var li = this.options.parent.getElement('.selected');
        if (li)
        {
          
          if (event.key == 'up')
          {                    
            var scroll = new Fx.Scroll(this.options.parent.parentNode, {
            	wait: true,
            	duration: 0,
              offset: {'x': 0, 'y': -18}//,
              // transition: Fx.Transitions.Quad.easeInOut
              ,
              onComplete: this.options.change()
            });
            scroll.toElement(li);
          }
          if (event.key == 'down')
          {
            this.options.change();
            var scroll = new Fx.Scroll(this.options.parent.parentNode, {
            	wait: true,
              duration: 0,
              offset: {'x': 0, 'y': 0}//,
              // transition: Fx.Transitions.Quad.easeInOut
              // ,
              // onComplete: 
            });
            scroll.toElement(li);
          }
          
          // DOWN  
          if (event.key == 'down')
          {
            if (li.hasClass('open') && li.getElement('ul'))
            {
              // alert('doing immerse + First');
              li = li.getElement('ul').getFirst();
            }
            else {
              if (li.getNext())
              {
                // alert('doing next');
                li = li.getNext();
              }
              else if (li == li.parentNode.getLast())
              {
                if (li.parentNode.parentNode.getNext())
                {
                  li = li.parentNode.parentNode.getNext();
                }
                else {
                  li = this.get_first_item(li.parentNode.parentNode, this);
                }
              }
            }
            li.fireEvent('k_click');
          }
          // UP
          if (event.key == 'up')
          {
            if (li.getPrevious())
            {
              if (li.getPrevious().hasClass('open') && li.getPrevious().getElement('ul'))
              {
                if (li.getPrevious().getElement('ul').getLast().hasClass('open'))
                {
                  li = this.get_last_item(li.getPrevious(), this);
                }
                else {
                  li = li.getPrevious().getElement('ul').getLast();
                }
              }
              else {
                li = li.getPrevious();
              }
            }
            else if (li == li.parentNode.getFirst())
            {
              li = li.parentNode.parentNode;
            }
            li.fireEvent('k_click');
          }
          // RIGHT
          if (event.key == 'right')
          {
            var li = this.options.parent.getElement('.selected .arrow');
            if (!li.hasClass('open'))
            {
              li.fireEvent('k_click');
            }
          }
          // LEFT
          if (event.key == 'left')
          {
            var li = this.options.parent.getElement('.selected .arrow');
            if (li.hasClass('open'))
            {
              li.fireEvent('k_click');
            }
          }
        }
      }
    }.bind(this));
  },
  get_last_item: function(li, tree){
    var ul = li.getElement('ul');
    var li = ul.getLast();
    if (li.hasClass('open'))
    {
      var li = tree.get_last_item(li, tree);
    }
    return li;
  },
  get_first_item: function(li, tree){
    if (!li.getNext())
    {
      li = tree.get_first_item(li.parentNode.parentNode, tree);
    }
    else {
      li = li.getNext();
    }
    return li;
  },
  refresh: function(){
    // alert('refreshiing...');
    // this.parent.empty();
    // alert(this.container.getProperty('class')+this.container.get('tag'));
    this.container.getElement('ul').empty();
    this.container = this.container.getElement('ul');
    new tree(this);
  }
});
