//   ____  _____ _____    _____ _____ _____ _____ _____              _   _
//  |    \|   __| __  |  |  _  |  |  |   | |  |  |_   _|   ___ _____| |_| |_
//  |  |  |   __|    -|  |   __|  |  | | | |    -| | |    | . |     | . |   |
//  |____/|_____|__|__|  |__|  |_____|_|___|__|__| |_|    |_  |_|_|_|___|_|_|
//                                                        |___|     Karlsruhe
//  Fabian Beiner <fbe@derpunkt.de>

var CustomSelect = new Class({
  Implements: Events,
  initialize: function(selectArea){
    if(!selectArea) { return (false); }
    this.selectArea = selectArea;
    this.selectList = false;
    this.selected = false;
    this.selectOpen = false;
    this.buildContents();
    this.selectElement = $(selectArea).getElement('select');
    this.selectElement.setStyle('display', 'none');
    this.elements = this.selectElement.getChildren().each(function(child) {
      if(child.get('tag') == 'optgroup') {
        this.addOptionGroup(child);
      } else {
        this.addOption(child);
      }
    }.bind(this));
    this.bindEvents();
  },
  buildContents: function() {
    this.selectField = new Element('div', {
      'class': 'selectField'
    });
    this.dropArea = new Element('div', {
      'class': 'status'
    });
    this.selectedOption = new Element('div', {
      'class': 'selected'
    });
    this.optionContainer = new Element('div', {
      'class': 'optContainer',
      'html': ''
    });
    this.selectedOption.inject(this.dropArea);
    this.dropArea.inject(this.selectField);
    this.optionContainer.inject(this.selectField);
    this.selectField.inject(this.selectArea, 'top');
  },
  bindEvents: function() {
    this.dropArea.addEvents({
      'click': function(e){
        if(this.selectOpen == true) {
          this.hideList();
        } else {
          new Event(e).stop();
          this.hideAllLists();
          this.showList();
        }
      }.bind(this)
    });
    document.addEvent('click', function() {
      this.hideList();
    }.bind(this));
  },

  addOptionGroup: function(optionGroup) {
    var group = new Element('div').addClass('optGroup');
    var label = new Element('div').addClass('optLabel');
    var optList  = new Element('div').addClass('optList');
    optList.inject(group);
    label.set('text', optionGroup.getProperty('label'));
    label.inject(group, 'top');
    optionGroup.getElements('option').each(function(option) {
      newOption = this.returnOption(option);
      newOption.inject(optList);
    }.bind(this));
    group.inject(this.optionContainer);

  },
  addOption: function(option) {
    newOption = this.returnOption(option);
    newOption.inject(this.optionContainer);
  },
  returnOption: function(option) {
    changeSelected = true;
    var newOption = new Element('div', {
      'class': 'opt',
      'html': option.text
    });
    var internRegex = new RegExp('(ftp|http|https):\/\/(\w+:{0,1}\w*@)?'+document.domain+'?(\/|\/([\w#!:.?+=&%@!\-\/]))?');
    var linkRegex = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;
    if (option.value.match(internRegex)) {
      newOption.addEvents({
        'click': function(e){
          new Event(e).stop();
          window.location = option.value;
          changeSelected = false;
        }.bind(this)
      });
    } else if (linkRegex.test(option.value)) {
      newOption.addEvents({
        'click': function(e){
          new Event(e).stop();
          window.open(option.value);
          changeSelected = false;
        }.bind(this)
      });
    }
    if($defined(option.getProperty('class')) && $chk(option.getProperty('class'))) {
      newOption.addClass(option.getProperty('class'));
    }
    if(option.disabled) {
      newOption.addClass('disabled')
    } else {
      newOption.addEvents({
        'click': this.onOptionClick.bindWithEvent(this),
        'mouseout': this.onOptionMouseout.bindWithEvent(this),
        'mouseover': this.onOptionMouseover.bindWithEvent(this)
      })
    }
    if(option.selected) {
      if(this.selected) { this.selected.removeClass('selected'); }
      this.selected = newOption;
      newOption.addClass('selected');
      this.selectedOption.set('html', option.text);
    }
    newOption.value = option.value;
    return newOption;
  },
  onOptionClick: function(e) {
    var event = new Event(e);
    if(this.selected != event.target && changeSelected) {
      this.selected.removeClass('selected');
      event.target.addClass('selected');
      this.selected = event.target;
      this.selectedOption.set('text', this.selected.getText());
      this.selectElement.value = event.target.value;
    }
    this.hideList();
  },
  onOptionMouseover: function(e) {
    var event = new Event(e);
    event.target.addClass('over');
  },
  onOptionMouseout: function(e) {
    var event = new Event(e);
    event.target.removeClass('over');
  },
  showList: function() {
    if(this.selectOpen == false) {
      this.selectOpen = true;
      this.optionContainer.setStyle('display','block');
      this.selectField.setStyle('z-index', 100000);
    }
  },
  hideList: function() {
    if(this.selectOpen == true) {
      this.selectOpen = false;
      this.optionContainer.setStyle('display','none');
      this.selectField.setStyle('z-index', 1);
    }
  },
  hideAllLists: function() {
    $each($$('.selectField'), function(value) {
      value.selectOpen = false;
      value.setStyle('z-index', 1);
    });
    $each($$('.selectField .optContainer'), function(value) {
      value.setStyle('display','none');
    });
  }
});
