/**
 * Opinions list controller
 */
OpinionsController = function(config) {
  // configurable {
  this.selector = ''; // required
  this.form_config = {}
  // }
  
  this.id = '';
  this.received_data = '';
  
  $.extend(this, config);
}

OpinionsController.prototype = {
  start: function() {
    this.id = this.getEl().generateId().attr('id');
    if(this.getFormOpinionId())
      this._moveFormToOpinion(this.getFormOpinionId());

    this._initFormController();

    this.getOpinionLink().click($.proxy(this.onClickOpinionLink, this));
    this.getAnswerLinks().click($.proxy(this.onAnswerClick, this));
  },

  _initFormController: function() {
    var config = $.extend({}, {
      selector: $('form', this.getFormEl()).getIdSelector(),
      hints: null,
      listeners: {
        received: this.onDataReceived,
        scope: this
      }
    }, this.form_config);
    var controller = new OpinionFormController(config);
    controller.init();
  },
  
  setFormToOpinion: function() {
    var prev_id = this.getFormOpinionId();
    if(prev_id == 0) {
      this.toggleForm();
      return;
    }
      
    this.getOpinionPlaceEl().append(this.getFormEl());
    this.setFormOpinionId(0);
    this._removeAnswerRow(prev_id);
    this.deactivateAnswerLink(prev_id);
    this.showForm();
  },
  
  setFormToAnswer: function(opinion_id) {
    var prev_id = this.getFormOpinionId();
    if(prev_id == opinion_id) {
      this.toggleForm();
      return;
    }

    this._moveFormToOpinion(opinion_id);      
    
    if(prev_id) {
      this._removeAnswerRow(prev_id);
      this.deactivateAnswerLink(prev_id);
    }
  },
  
  _moveFormToOpinion: function(opinion_id) {
    this._createAnswerRow(opinion_id);
    this.getAnswerCell(opinion_id).append(this.getFormEl());
    this.setFormOpinionId(opinion_id);
    this.getFormEl().show();
    this.deactivateOpinionLink();
    this.activateAnswerLink(opinion_id);
  },
  
  toggleForm: function() {
    if(this.isFormShown())
      this.hideForm();
    else
      this.showForm();
  },
  
  hideForm: function() {
    this.getFormEl().hide();
    var opinion_id = this.getFormOpinionId();
    if(opinion_id == 0)
      this.deactivateOpinionLink();
    else
      this.deactivateAnswerLink(opinion_id);
  },
  
  showForm: function() {
    this.getFormEl().show();
    var opinion_id = this.getFormOpinionId();
    if(opinion_id == 0)
      this.activateOpinionLink();
    else
      this.activateAnswerLink(opinion_id);
  },
  
  isFormShown: function() {
    return this.getFormEl().is(':visible');
  },
  
  activateAnswerLink: function(opinion_id) {
    this.getAnswerLink(opinion_id).parent().addClass('act');
  },
  
  deactivateAnswerLink: function(opinion_id) {
    this.getAnswerLink(opinion_id).parent().removeClass('act');
  },
  
  activateOpinionLink: function() {
    this.getOpinionLink().parent().addClass('act');
  },
  
  deactivateOpinionLink: function() {
    this.getOpinionLink().parent().removeClass('act');
  },
  
  _createAnswerRow: function(opinion_id) {
    this.getOpinionCellByOpinionId(opinion_id).parent()
        .after('<tr class="answer-row"><td class="answer-cell"></td></tr>');
  },
  
  _removeAnswerRow: function(opinion_id) {
    this.getAnswerRow(opinion_id).remove();
  },
  
  getFormOpinionId: function() {
    return parseInt(this.getFormOpinionIdEl().val()) || 0;
  },
  
  setFormOpinionId: function(opinion_id) {
    this.getFormOpinionIdEl().val(opinion_id);
  },
  
  getAnswerCell: function(opinion_id) {
    return this.getAnswerRow(opinion_id).children('.answer-cell');
  },
  
  getAnswerRow: function(opinion_id) {
    return this.getOpinionCellByOpinionId(opinion_id).parent().next('.answer-row');
  },
  
  getOpinionIdFromOpinionCell: function($opinion_cell) {
    var id = $opinion_cell.attr('id');
    if(!id) 
      return 0;
      
    var id_prefix = this.id + '-opinion-';
    if(id.indexOf(id_prefix) != 0)
      return 0;
      
    return parseInt(id.substr(id_prefix.length)) || 0;
  },
  
  getFormOpinionIdEl: function() {
    return $('input[name=opinion_id]', this.getFormEl());
  },
  
  getOpinionCellByOpinionId: function(id) {
    return $('#' + this.id + '-opinion-' + id);
  },
  
  getOpinionLink: function() {
    return $('#' + this.id + '-opinion-link a');
  },
  
  getFormEl: function() {
    return $('#' + this.id + '-form');
  },
  
  getAnswerLink: function(opinion_id) {
    return $('div.controls .answer a', this.getOpinionCellByOpinionId(opinion_id));
  },
  
  getAnswerLinks: function() {
    return $('div.controls .answer a', this.getEl());
  },
  
  getOpinionCellByInnerEl: function(el) {
    return $(el).parents('.opinion-cell');
  },
  
  getOpinionPlaceEl: function() {
    return $('#' + this.id + '-opinion-place');
  },
  
  getEl: function() {
    return $(this.selector);
  },
  
  onClickOpinionLink: function() {
    this.setFormToOpinion();
    return false;
  },
  
  onAnswerClick: function(e) {
    var opinion_id = this.getOpinionIdFromOpinionCell(this.getOpinionCellByInnerEl(e.target));
    if(opinion_id)
      this.setFormToAnswer(opinion_id);
      
    return false;
  },

  onDataReceived: function(controller, data, sent_data) {
    this.setFormToOpinion();
    this.hideForm();
    
    var $prev_row = null;
    if(sent_data.opinion_id == 0) {
      $prev_row = $('td.opinion-cell:last, td.no-opinions', this.getEl()).parent();
    } else {
      $prev_row = $('td.parent-' + sent_data.opinion_id + ':last', this.getEl()).parent();
      if($prev_row.length == 0)
        $prev_row = this.getOpinionCellByOpinionId(sent_data.opinion_id).parent();
    }
    
    var $new_row = $prev_row.after(data).next().hide();
    
    if($prev_row.children('td.no-opinions').length > 0)
      $prev_row.remove();
      
    $new_row.find('div.controls .answer a').click($.proxy(this.onAnswerClick, this));
    $new_row.fadeIn('slow');
  }
}


/**
 * Opinion form controller
 */
OpinionFormController = function(config) {
  // configurable {
  this.selector = ''; // required
  this.loader_img = '/i/ajax-loader.gif';
  this.captcha_url = '/tcaptcha.php';
  this.hints = null; // hints collection
  // }
  
  this.x_field = '';
  this.y_field = '';
  this.sending = false;
  this.sent_data = {};

  this.addEvents({
    received: true
  });

  OpinionFormController.superclass.constructor.call(this, config);
}

utils.extend(OpinionFormController, utils.Observable, {
  init: function() {
    this.initCaptcha();
    this.initEvents();
  },
  
  initCaptcha: function() {
    var name = this.getButtonName();
    this.x_field = name + '_x';
    this.y_field = name + '_y';
    this.getEl().append('<input type="hidden" name="' + this.x_field +'"/>')
                .append('<input type="hidden" name="' + this.y_field +'"/>');    
  },
  
  initEvents: function() {
    this.getEl().submit($.proxy(this.onSubmit, this));
    this.getImageButton().click($.proxy(this.onButtonClick, this));
  },
  
  send: function(values) {
    var values = $.extend({}, values);
    values[this.x_field] = this.getXField().val();
    values[this.y_field] = this.getYField().val();
    this.sent_data = values;
    this.showLoader();
    this.sending = true;
    $.post(
      this.getEl().attr('action'),
      values,
      $.proxy(this.onSuccessRequest, this)
    );
  },
  
  validate: function(values) {
    var errors = [];
    if(!values.name)
      errors.push('введите Ваше имя');
    if(values.rating == 'no' && !values.content)
      errors.push('поставьте оценку или напишите отзыв');
    
    return errors;
  },
  
  getButtonName: function() {
    return this.getImageButton().attr('name');
  },
  
  getImageButton: function() {
    return $('input[type=image]', this.getEl());
  },
  
  getValues: function(name) {
    var values = {
      name: '',
      rating: '',
      product_id: 0,
      opinion_id: 0,
      email: '',
      content: ''
    }
    var $el = this.getEl();
    $.each(values, function(name) {
      var $input = $(':input[name=' + name + ']:not(:radio), input:radio[name=' + name + ']:checked', $el);
      if($input.length > 0)
        values[name] = $.trim($input.val());
    });
    return values;
  },
  
  showLoader: function() {
    this.getResponseEl().html(
      '<img src="' + this.loader_img + '" alt=""/> Отправка данных...'
    );
  },
  
  cleanResponse: function() {
    this.getResponseEl().html('');
  },
  
  cleanForm: function() {
    $(':input[name=content]', this.getEl()).val('');
    $(':input[name=rating]', this.getEl()).val(['no']);
  },
  
  refreshCaptcha: function() {
    this.getCaptcha().attr('src', this.captcha_url + '?' + Math.random());
  },
  
  showResponseError: function(message) {
    this.getResponseEl().html(
      '<div class="error">' + message + '</div>'
    );
  },
  
  showResponseSuccess: function() {
    this.getResponseEl().html('Ваш отзыв принят. Спасибо!');
  },
  
  _analyseResponse: function(data) {
    this.refreshCaptcha();

    var flag = data.length > 0 ? data.substr(0, 1) : '';
    switch(flag) {
      case '+':
        this.showResponseSuccess();
        this.cleanForm();
        this.fireEvent('received', [ this, data.substr(1), this.sent_data ]);
        break;
      case '-':
        this.showResponseError(data.substr(1));
        break;
      default:
        alert('Произошла непредвиденная ошибка!\r\nПожалуйста, попробуйте отправить позже.\r\nПриносим извинения за доставленные неудобства ;-(');
    }
  },
  
  getXField: function() {
    return $('[name=' + this.x_field + ']', this.getEl());
  },
  
  getYField: function() {
    return $('[name=' + this.y_field + ']', this.getEl());
  },
  
  getResponseEl: function() {
    return $('.response', this.getEl());
  },
  
  getCaptcha: function() {
    return $('.code_image', this.getEl());
  },
  
  getEl: function() {
    return $(this.selector);
  },
  
  onSubmit: function() {
    if(this.sending)
      return false;
    
    if(this.hints)
      this.hints.unsync();
      
    var values = this.getValues();
    var errors = this.validate(values);
    if(errors.length > 0) {
      var message = 'Не все поля заполнены правильно:\r\n-';
      message += errors.join('\r\n-');
      alert(message);
    } else {
      this.showLoader();
      this.send(values);
    }

    if(this.hints)
      this.hints.sync();
      
    return false;
  },
  
  onButtonClick: function(e) {
    var offset = this.getImageButton().offset();
    this.getXField().val(Math.round(e.pageX - offset.left));
    this.getYField().val(Math.round(e.pageY - offset.top));
  },
  
  onSuccessRequest: function(data) {
    this.sending = false;
    this.cleanResponse();
    this._analyseResponse($.trim(data));
  }
});
