ns('Carib.Order.Widgets');

/**
 * Abstract class of field
 * 
 * @version $Id: fields.js 547 2009-09-14 15:18:36Z  $
 */
Carib.Order.Widgets.Field = function(config) {
  // configurable {
  this.selector = ''; //required
  this.name = '';
  this.auto_init = false;
  this.id = false;
  this.value = '';
  // }
  
  this.addEvents({
    change: true
  });
  
  Carib.Order.Widgets.Field.superclass.constructor.call(this, config);
  
  if(this.auto_init)
    this.init();
}

utils.extend(Carib.Order.Widgets.Field, utils.Observable, {
  init: function() {
    this._initEvents();
  },
  
  _initEvents: function() {
    
  },
  
  setValue: function(value) {
    if(this.value === value)
      return;
      
    this.value = value;
    this.setRawValue(value);
    this.onChange();
  },
  
  setRawValue: function(value) {
    
  },
  
  getValue: function() {
    return this.value;
  },
  
  getRawValue: function() {
    
  },
  
  getName: function() {
    return this.name;
  },
  
  getId: function() {
    if(this.id === false) {
      this.id = this.getEl().generateId().attr('id');
    }
    return this.id;
  },
  
  getEl: function() {
    return $(this.selector);
  },  

  onChange: function() {
    this.fireEvent('change', [this, this.getValue()]);
  }  
});


/**
 * Simple field
 */
Carib.Order.Widgets.SimpleField = function(config) {
  Carib.Order.Widgets.SimpleField.superclass.constructor.call(this, config);
}

utils.extend(Carib.Order.Widgets.SimpleField, Carib.Order.Widgets.Field, {
  _initEvents: function() {
    this.getEl().change(this._onRawChange.createDelegate(this));
  },
  
  setRawValue: function(value) {
    this.getEl().val(value);
  },
  
  getRawValue: function() {
    return this.getEl().val();
  },
  
  disable: function() {
    this.getEl().attr('disabled', 'true');
  },
  
  enable: function() {
    this.getEl().removeAttr('disabled');
  },
  
  hide: function() {
    this.getEl().hide();
  },
  
  show: function() {
    this.getEl().show();
  },
  
  _onRawChange: function() {
    this.value = this.getRawValue();
    this.onChange();
  }  
});


/**
 * Checkbox
 */
Carib.Order.Widgets.Checkbox = function(config) {
  Carib.Order.Widgets.Checkbox.superclass.constructor.call(this, config);
}

utils.extend(Carib.Order.Widgets.Checkbox, Carib.Order.Widgets.Field, {
  _initEvents: function() {
    this.getEl().click(this._onRawChange.createDelegate(this));
  },
  
  setRawValue: function(value) {
    if(value)
      this.getEl().attr('checked', 'true');
    else
      this.getEl().removeAttr('checked');
  },
  
  getRawValue: function() {
    return this.getEl().is(':checked');
  },
  
  disable: function() {
    this.getEl().attr('disabled', 'true');
  },
  
  enable: function() {
    this.getEl().removeAttr('disabled');
  },
  
  hide: function() {
    this.getEl().hide();
  },
  
  show: function() {
    this.getEl().show();
  },
  
  _onRawChange: function() {
    this.value = this.getRawValue();
    this.onChange();
  }  
});


/**
 * Date field
 */
Carib.Order.Widgets.DateField = function(config) {
  config = $.extend({
    value: new Date()
  }, config);
  
  Carib.Order.Widgets.DateField.superclass.constructor.call(this, config);
}

utils.extend(Carib.Order.Widgets.DateField, Carib.Order.Widgets.SimpleField, {
  init: function() {
    Carib.Order.Widgets.DateField.superclass.init.call(this);
    
    this._initDatePicker();
  },
  
  _initDatePicker: function() {
    this.getEl().datepicker({
      duration: '',
      buttonImageOnly: true,
      buttonText: 'календарь',
      buttonImage: '/i/calendar.gif',
      showOn: 'button',
      changeYear: true,
      changeMonth: true,
      yearRange: '-80:+10'
    });
  },
    
  setRawValue: function(value) {
    this.getEl().datepicker('setDate', value);
  },
  
  getRawValue: function() {
    return this.getEl().datepicker('getDate');
  }
  
});


/**
 * Select
 */
Carib.Order.Widgets.Select = function(config) {
  // configurable {
  this.recordset = null; // required
  this.id_value = 'id';
  this.display_value = 'name';
  this.loader = null;
  this.empty_text = '-';
  this.loading_text = 'загружается...';
  // }
  this.is_empty = false;
  this.is_loading = false;
  
  this.addEvents({
    select: true,
    load: true,
    beforeload: true
  });
  
  Carib.Order.Widgets.Select.superclass.constructor.call(this, config);
}

utils.extend(Carib.Order.Widgets.Select, Carib.Order.Widgets.SimpleField, {
  init: function() {
    Carib.Order.Widgets.Select.superclass.init.call(this);
    
    this._addInitialRows();
    this._processEmpty();
  },
  
  _addInitialRows: function() {
    this.recordset.each(function(num, record) {
      this._addOption(record, num);
    }, this);
  },
  
  _initEvents: function() {
    Carib.Order.Widgets.Select.superclass._initEvents.call(this);
    
    this.recordset.on('add', this.onAddRecord, this);
    this.recordset.on('update', this.onUpdateRecord, this);
    this.recordset.on('remove', this.onRemoveRecord, this);
    if(this.loader) {
      this.loader.on('beforeload', this.onBeforeLoad, this);
      this.loader.on('load', this.onLoad, this);
    }
  },  
  
  _processEmpty: function() {
    if(this.recordset.getCount() > 0) {
      if(this.is_empty)
        this._setToNormal();
    } else {
      if(!this.is_empty)
        this._setToEmpty();
    }
  },
  
  _setToEmpty: function() {
    this.is_empty = true;
    $('<option></option>').appendTo(this.getEl())
                          .attr('id', this._generateEmptyOptionId())
                          .html(this.empty_text);
    this.disable();
  },
  
  _setToNormal: function() {
    this.is_empty = false;
    this.is_loading = false;
    $(this._generateEmptyOptionSelector()).remove();    
    $(this._generateLoadingOptionSelector()).remove();    
    this.enable();
  },
  
  _setToLoading: function() {
    this.is_loading = true;
    this.recordset.removeAll();
    this._setToNormal();
    $('<option></option>').appendTo(this.getEl())
                          .attr('id', this._generateLoadingOptionId())
                          .html(this.loading_text);
                          
    this.disable();
  },
  
  _addOption: function(record, num) {
    $('<option></option>').appendTo(this.getEl())
                          .attr('id', this._generateOptionId(record))
                          .attr('value', record.get(this.id_value))
                          .html(record.get(this.display_value));
    this._processEmpty();
  },
  
  _updateOption: function(record, num) {
    $(this._generateOptionSelector(record)).attr('value', record.get(this.id_value))
                                        .html(record.get(this.display_value));
  },
  
  _removeOption: function(record, num) {
    $(this._generateOptionSelector(record)).remove();
    this._processEmpty();
  },
  
  load: function(options, no_reset) {
    options = $.extend(options || {}, { recordset: this.recordset });
    this.loader.load(options);
    
    if(!no_reset)
      this.value = null;
  },
  
  _generateOptionSelector: function(record) {
    return '#' + this._generateOptionId(record);
  },
  
  _generateOptionId: function(record) {
    return this.getId() + '_opt_' + record.getId();
  },
  
  _generateEmptyOptionSelector: function() {
    return '#' + this._generateEmptyOptionId();
  },
  
  _generateEmptyOptionId: function() {
    return this.getId() + '_opt_empty';
  },
  
  _generateLoadingOptionSelector: function() {
    return '#' + this._generateLoadingOptionId();
  },
  
  _generateLoadingOptionId: function() {
    return this.getId() + '_opt_loading';
  },
  
  getSelected: function() {
    var num = this.recordset.findRecord(this.getValue());
    return num === false ? null : this.recordset.getAt(num);
  },
  
  getRecordset: function() {
    return this.recordset;
  },
  
  isEmpty: function() {
    return this.is_empty;
  },
  
  isLoading: function() {
    return this.is_loading;
  },
  
  onAddRecord: function(recordset, record, num) {
    this._addOption(record, num);
  },
  
  onUpdateRecord: function(recordset, record, num) {
    this._updateOption(record, num);
  },
  
  onRemoveRecord: function(recordset, record, num) {
    this._removeOption(record, num);
  },
  
  onBeforeLoad: function() {
    this._setToLoading();
    this.fireEvent('beforeload', [this]);
  },
  
  onLoad: function() {
    this._setToNormal();
    this._processEmpty();
    
    if(this.recordset.getCount() > 0) {
      if(this.value !== null)
        this.setRawValue(this.value);
      else
        this.setValue(this.recordset.getAt(0).get(this.id_value));
    }
    
    this.fireEvent('load', [this, this.recordset]);
  }
});


/**
 * Multiselect
 * 
 * @param {Object} config
 */
Carib.Order.Widgets.MultiSelect = function(config) {
  // configurable {
  this.select = null; // required select
  // }
  this.recordset = new Carib.Order.Data.Recordset();
  this.add_disabled = false;
  
  Carib.Order.Widgets.MultiSelect.superclass.constructor.call(this, config);
}

utils.extend(Carib.Order.Widgets.MultiSelect, Carib.Order.Widgets.Field, {
  init: function() {
    Carib.Order.Widgets.MultiSelect.superclass.init.call(this);
    
    this.select.selector = '#' + this.getId() + ' ' + this.select.selector;
    this.select.init();
    
    this.disableAddIf();
  },
  
  _initEvents: function() {
    Carib.Order.Widgets.MultiSelect.superclass._initEvents.call(this);
    
    this.recordset.on('add', this.onAddRecord, this);
    this.recordset.on('update', this.onUpdateRecord, this);
    this.recordset.on('remove', this.onRemoveRecord, this);
    
    this.getAddButton().click(this.onAdd.createDelegate(this));
    
    this.select.on('load', this.onLoadSelect, this);
    this.select.on('beforeload', this.onBeforeLoadSelect, this);
    this.select.on('change', this.onSelectChange, this);
  },  
  
  _addRecord: function(record, num) {
    var $record_div = $('<div class="multiselect_row"></div>').appendTo(this.getListEl())
                    .attr('id', this._generateRecordId(record));
    var $del_span = $('<a href="javascript:void(0)" class="del ui-state-hover ui-corner-all" title="Удалить"><span class="ui-icon ui-icon-minusthick"></span></a>').appendTo($record_div);
    $del_span.click(this.onRemove.createDelegate(this, [record.getId()]));
    
    $('<span class="name"></span>').appendTo($record_div).html(record.get('name'));
  },
  
  _removeRecord: function(record, num) {
    $(this._generateRecordSelector(record), this.getListEl()).remove();
  },
  
  setValue: function(value) {
    this.recordset.removeAll();
    value.cloneTo(this.recordset);
  },
  
  getValue: function() {
    return this.recordset.getClone();    
  },
  
  getRecordset: function() {
    return this.recordset;
  },
  
  getSelect: function() {
    return this.select;
  },
  
  disableAddIf: function() {
    this.add_disabled = true;
    if(!this.select.isEmpty() && !this.select.isLoading()) {
      var selected = this.select.getSelected();
      if(selected) {
        if(this.recordset.findRecord(selected.getId()) === false)
          this.add_disabled = false;
      }
    }
    this.disableAddButon(this.add_disabled);
  },
  
  disableAddButon: function(disable) {
    if(disable)
      this.getAddButton().attr('disabled', 'true');
    else
      this.getAddButton().removeAttr('disabled');
  },
  
  getListEl: function() {
    return $('.selected_list', this.getEl());
  },
  
  getAddButton: function() {
    return $('.add_button', this.getEl());
  },
  
  addSelected: function() {
    if(this.add_disabled)
      return;
      
    var selected = this.select.getSelected();
    if(selected) {
      var record = new Carib.Order.Widgets.MultiSelect.Record();
      record.setId(selected.getId());
      record.set('name', selected.get(this.select.display_value));
      this.recordset.add(record);
    }
    
    this.disableAddIf();
  },
  
  remove: function(id) {
    this.recordset.remove(id);
    this.disableAddIf();
  },
  
  _generateRecordSelector: function(record) {
    return '#' + this._generateRecordId(record);
  },
  
  _generateRecordId: function(record) {
    return this.getId() + '_rec_' + record.getId();
  },
  
  onAddRecord: function(recordset, record, num) {
    this._addRecord(record, num);
  },
  
  onUpdateRecord: function(recordset, record, num) {
  },
  
  onRemoveRecord: function(recordset, record, num) {
    this._removeRecord(record, num);
  },
  
  onRemove: function(id) {
    this.remove(id);
  },
  
  onAdd: function() {
    this.addSelected();
  },
  
  onLoadSelect: function() {
    this.disableAddIf();
  },
    
  onSelectChange: function() {
    this.disableAddIf();
  },
    
  onBeforeLoadSelect: function() {
    this.disableAddIf();
  },
    
  getListEl: function() {
    return $('.selected_list', this.getEl());
  }
});

/**
 * Multiselect record
 */
Carib.Order.Widgets.MultiSelect.Record = function(values) {
  Carib.Order.Widgets.MultiSelect.Record.superclass.constructor.call(this, {
    name: '' // название
  }, values);  
}

utils.extend(Carib.Order.Widgets.MultiSelect.Record, Carib.Order.Data.Record);


/**
 * Excursions select
 * 
 * @param {Object} config
 */
Carib.Order.Widgets.ExcursionsSelect = function(config) {
  Carib.Order.Widgets.ExcursionsSelect.superclass.constructor.call(this, config);
}

utils.extend(Carib.Order.Widgets.ExcursionsSelect, Carib.Order.Widgets.MultiSelect, {
  _addRecord: function(record, num) {
    var $record_div = $('<div class="multiselect_row"></div>').appendTo(this.getListEl())
                    .attr('id', this._generateRecordId(record));
    var $del_span = $('<a href="javascript:void(0)" class="del ui-state-hover ui-corner-all" title="Удалить"><span class="ui-icon ui-icon-minusthick"></span></a>').appendTo($record_div);
    $del_span.click(this.onRemove.createDelegate(this, [record.getId()]));
    
    var $info_span = $('<a href="/countries/excursion/' + record.getId() + '/" target="_blank" class="info ui-state-hover ui-corner-all" title="Информация"><span class="ui-icon ui-icon-extlink"></span></a>').appendTo($record_div);
    
    $('<span class="name"></span>').appendTo($record_div).html(record.get('name'));
  }    
});



/**
 * Nights field
 */
Carib.Order.Widgets.NightsField = function(config) {
  // configurable {
  this.input_html = '<input type="text"/>';
  this.select_html = '<select/>'; 
  // }
  
  Carib.Order.Widgets.NightsField.superclass.constructor.call(this, config);
}

utils.extend(Carib.Order.Widgets.NightsField, Carib.Order.Widgets.SimpleField, {
  transformToSelect: function(values) {
    var id = this.getId();
    var $select = $(this.select_html).attr({
      id: id,
      name: this.name
    });
    this.getEl().replaceWith($select);
    
    this.addValues(values);

    this._initAfterTransform();    
  },
  
  transformToInput: function() {
    var id = this.getId();
    var $input = $(this.input_html).attr({
      id: id,
      name: this.name
    });
    this.getEl().replaceWith($input);

    this._initAfterTransform();    
  },
  
  hasOption: function(value) {
    return $('option[value=' + value + ']', this.getEl()).length > 0;
  },
  
  setFirstValue: function() {
    var value = $('option', this.getEl()).eq(0).val();
    if(!value)
      value = 1;
      
    this.setValue(value);
  },
  
  _initAfterTransform: function() {
    if(this.value !== null)
      this.setRawValue(this.value);
      
    this._initEvents();
  },
  
  /**
   * Parse values
   * @param {String} values
   * @return {Array}
   */
  _parseValues: function(values) {
    return values.split(/[,; ]+/);
  },
  
  /**
   * Add values to select
   * 
   * @param {String} values
   */
  addValues: function(values) {
    values = this._parseValues(values);
    for(var i = 0, l = values.length; i < l; i ++) {
      var $option = $('<option/>').attr('value', values[i]).html(values[i]);
      $option.appendTo(this.getEl());
    }
  }
});
