function Calculator()
{
  // конструктор
  IE  = !!document.all;
  IE6 = navigator.userAgent.indexOf('MSIE 6') > -1;

  this.type = $('calc_type');
  this.host = $('calc_host');
  this.region = $('calc_region_wrap');
  this.age = $('calc_age');
  this.power = $('calc_power');
  this.period = $('calc_period');

  this.result = 0;
  this.debug = '';

  this.fields = {
    'type':   'Тип ТС',
    'host':   'Собственник ТС',
    'region': 'Место регистрации ТС',
    //'bonus':  'Класс бонуса-малуса',
    'limit':  'Лица, допущенные к управлению',
    'age':    'Минимальный возраст и стаж водителя, допущенного к управлению',
    'power':  'Мощность двигателя (л.с.)',
    'period': 'Сколько месяцев в году используется ТС'
  };

}


Calculator.prototype = {

  /**
   * Инициализация калькулятора. Прорисовка всех полей и навешивание на них нужных обработчиков.
   */
  init: function()
  {
    // Заполнение селектов значениями

    // Тип ТС (категория)
    for(var key in data.type)
      addElement(this.type, 'option', {'value': key}, data.type[key]['name']);


    // Собственник ТС
    for(var key in data.host)
      addElement(this.host, 'option', {'value': key}, data.host[key]);


    // Возраст и стаж
    for(var key in data.age)
      addElement(this.age, 'option', {'value': key}, data.age[key]['name']);


    // Мощность двигателя
    for(var key in data.power)
      addElement(this.power, 'option', {'value': key}, data.power[key]['name']);


    // Сколько месяцев в году используется
    for(var key in data.period)
      addElement(this.period, 'option', {'value': key}, data.period[key]['name']);


    // Регион
    var label, div;
    var str = '';
    for(var key in data.region)
    {
      str += '<div>';
      str += '<input class="nb" type="radio"';
      if (key == 1) str += ' checked="checked"';
      str += 'value="' + key + '" id="region' + key + '" name="region"/>';
      str += '<label for="region'+ key +'"';
      if (key >3 && key <14) str += ' class="textarea"';
      str += '>'+ data.region[key]['name'] +'</label>';
      str += '</div>';
    }
    this.region.innerHTML = str;


    /////////////////////////////////////////////////////////////////
    // Если выбрано "юридическое лицо" делаем активным только "нет ограничения"
    this.host.onchange = function()
    {
      var disabled, className;
      if (this.value == 'legal') // юридическое лицо
      {
        disabled = true;
        className = 'unactive';

        $('calc_nolimit').checked = true;
        $('calc_age').disabled = true;
      }
      else {
        var disabled = false;
        className = '';
      }

      $('calc_limit_label').className = className;
      $('calc_limit').disabled = disabled;
    };



    /////////////////////////////////////////////////////////////////
    // Если выбрано "Конкретные водители будут вписаны в полис" показываем блок с выбором стажа
    $('calc_limit').onclick = function() {
      $('calc_age').disabled = false;
    }

    $('calc_nolimit').onclick = function() {
      $('calc_age').disabled = true;
    }


    /////////////////////////////////////////////////////////////////
    // Если выбрано "категория B" показываем блок с мощностью двитателя
    this.type.onchange = function()
    {
      return;
      if (this.value == 2) {
        $('calc_power_row').style.display = (IE) ? 'block' : 'table-row';
        $('calc_power').style.display = 'block';
      }
      else {
        $('calc_power_row').style.display = 'none';
        $('calc_power').style.display = 'none';
      }
    };



  },


  calculate: function() {

    // Расчёт коэффициентов для формулы
    var factor = {};
    var i;

    ////////////////////////////////////
    // Категория ТС
    if(this.type.value == 2)
      factor.type = data.type[this.type.value][this.host.value];
    else
      factor.type = data.type[this.type.value].cost;


    ////////////////////////////////////
    // Место регистрации
    var region = document.forms['calc_form'].elements['region'];
    var reg, c = 0;

    // узнаём какое выбрано значение
    for(i = 0, size = region.length; i < size; i++)
    {
      if (region[i].checked == true)
      {
        reg = region[i].value;
        break;
      }
    }

    factor.region = this.validate('region', reg);
    this.region = {value: reg}



    ////////////////////////////////////
    // Лица, допущенные к управлению
    var face;
    c = 0;

    if ($('calc_limit').checked == true) {
      this.limit = {value: 'limit'};
      face_fill = true;
    }
    else if ($('calc_nolimit').checked == true) {
      this.limit = {value: 'nolimit'};
      face_fill = true;
    }
    else {
      this.limit = {value: 'nolimit'};
      face_fill = false; // если не заполнено поле "лица, допущенные к управлению"
    }

    for(i = 0, size = validate.limit.length; i < size; i++)
    {
      if (this.type.value == validate.limit[i])
      {
        factor.limit = data.limit[this.limit.value].factor2;
        break;
      }
      else c++;
    }

    if(face_fill == false)
    {
      factor.limit = data.limit['nolimit'].factor2;
      c = size--;
    }

    // если выполняется, значит берем коэффициент из 1 столбца
    if (c == size)
      factor.limit = data.limit[this.limit.value].factor;



    ////////////////////////////////////
    // Минимальный возраст и стаж
    if ($('calc_nolimit').checked == true)
      mode = 2;
    else
      mode = 1;

    factor.age = this.validate('age', $('calc_age').value, mode);



    ////////////////////////////////////
    // Мощность двигателя
    if(this.type.value == 2) // ТС категории B
    {
      factor.power = data.power[$('calc_power').value].factor;
    }
    else factor.power = 1;



    ////////////////////////////////////
    // Период использования ТС
    factor.period = data.period[$('calc_period').value].factor;




    ////////////////////////////////////
    // Расчёт результата по формуле
    // тип ТС * место регистрации ТС * лица, допущенные к управлению * Минимальный возраст и стаж * мощность двигателя ТС (л.с.) * период использования ТС (мес.)
    this.result = factor.type * factor.region * factor.limit * factor.age * factor.power * factor.period




    var f = '', m;
    // формирование строки для записи в hidden-поле
    for(key in data)
    {
      if(key == 'host')
        m = data[key][ this[key].value ];
      else
        m = data[key][ this[key].value ]['name'];

      f += this.fields[key] + ': '+ m + '\n';
    }

    // проверка результата
    var check = factor.type * factor.region * 3;
    if(this.result > check)
      this.result = check;

    // бьём строку по разделителю '.'
    var pieces = String(this.result).split('.');
    if(typeof(pieces[1]) != 'undefined') // если есть дробная часть
      this.result = pieces[0] + ',' + pieces[1].substr(0, 2); // 2 знака

    $('result').value = this.result;

    f += '\nСтраховой тариф составит: ' + this.result + 'р.';
    $('calc_data').value = f;

    $('calc_text').style.display = 'block';
    //$('debug').innerHTML = f;
   },


  /**
   * Валидатор
   * @param {} obj
   * @param {} m
   * @param {} mode Если передан, значение всегда берётся из второй колонки
   * @return {}
   */
  validate: function(obj, m, mode) {
    if( m == false || typeof(m) == 'undefined' )
      return false;

    var c = 0;
    var r;

    for(var i = 0, size = validate[obj].length; i < size; i++)
    {
      /*
       * если хоть один раз выполнилось условие, значит:
       * выполнилось условие для 2 столбца и коэффициент берём оттуда
       */
      if (this.type.value == validate[obj][i])
      {
        r = data[obj][m].factor2;
        return r;
      }
      else c++;
    }

    if(mode == 2)
    {
      r = data[obj][m].factor2;
      return r;
    }

    // если выполняется, значит берем коэффициент из 1 столбца
    if (c == size)
      r = data[obj][m].factor;

    return r;
  },



 /**
 * Получает стиль элемента
 * @param {DOMElement} obj элемент стиль которого нужно получить
 * @param {String} style CSS-свойство, которое надо получить
 * @return {String}
 */
  getStyle: function(obj, style)
  {
    // DOM 2
    if(document.defaultView)
      return document.defaultView.getComputedStyle(obj, null)[style];
    // IE
    else if (obj.currentStyle)
      return obj.currentStyle[style];
  },



  /**
   * Скрывает/показывает элемент
   * @param {DOMElement} obj
   */
  toggle: function(obj) {
    var style = this.getStyle(obj, 'display');
    var d;

    if(style == 'none')
      d = 'block';
    else
      d = 'none';

    obj.style.display = d;
  }


}




/**
 * Сокращённая запись document.getElementById
 * @param {String} id Айдишник элемента, который надо получить
 * @return {Object} Запрошенный элемент DOM
 */
function $(id) {
    return document.getElementById(id);
}



/**
 * Добавляет новый html-элемент (тэг)
 * @param {String} parent Родитель нового элемента. Ex: $('el'), document.body
 * @param {String} ename Название добавляемого тега. Ex: 'option', 'em'
 * @param {Object} attrs Хэш с атрибутами добавляемого тега. Ex: {'id': 'new', 'width': '50%'}
 * @param {String} innerHTML Текст внутри добавляемого тэга
 * @return {DOMElement}
 */
function addElement(parent, ename, attrs, text) {
    var el = document.createElement(ename);
    var key = null;
    if(typeof(attrs) == 'object')
    {
      for(key in attrs)
          el.setAttribute(key, attrs[key]);
    }
    if(text) el.innerHTML = text;

    return parent.appendChild(el);
}