//------------------------------------------------------------------------------
/** @author Бреславский А.В. (Joonte Ltd.) */
//------------------------------------------------------------------------------
$Links = {};
//------------------------------------------------------------------------------
var HTTP = function(){
  //----------------------------------------------------------------------------
  // Ресурс HTTP соединения
  this.Resource = null;
  // Идентификатор ссылки в глобальном массиве Links
  this.LinkID = 'HTTP-' + (Math.round(Math.random()*8999) + 1000);
  // Стэк запросов
  this.Stack = [];
  // Свободен ли объект для запроса
  this.IsFree = true;
  //----------------------------------------------------------------------------
  $Links[this.LinkID] = this;
  //----------------------------------------------------------------------------
  if(window.XMLHttpRequest){
    //--------------------------------------------------------------------------
    // Mozilla, Safari,...
    var $Resource = new XMLHttpRequest();
  }else{
    //--------------------------------------------------------------------------
    if(window.ActiveXObject){
      // Internet Explorer
      try{
        $Resource = new ActiveXObject('Msxml2.XMLHttp');
      }catch(Exception){
        //----------------------------------------------------------------------
        try{
          $Resource = new ActiveXObject('Microsoft.XMLHttp');
        }catch(Exception){
          //--------------------------------------------------------------------
          alert('Ваш браузер не поддерживает Ajax');
          //--------------------------------------------------------------------
          return false;
        }
      }
    }
  }
  //----------------------------------------------------------------------------
  this.Resource = $Resource;
  //----------------------------------------------------------------------------
  return true;
};
//------------------------------------------------------------------------------
HTTP.prototype.IsCreated = function(){
  //----------------------------------------------------------------------------
  return Boolean(this.Resource);
};
//------------------------------------------------------------------------------
HTTP.prototype.Send = function($Url,$Args){
  //----------------------------------------------------------------------------
  if(!this.IsCreated()){
    //--------------------------------------------------------------------------
    Debug('[HTTP::Send]: ресурс на соединение не найден');
    //--------------------------------------------------------------------------
    return false;
  }
  //----------------------------------------------------------------------------
  if(!this.IsFree){
    //--------------------------------------------------------------------------
    this.Stack.push({Url:$Url,Args:$Args});
    //--------------------------------------------------------------------------
    return true;
  }
  //----------------------------------------------------------------------------
  if(typeof($Args) != 'object')
    var $Args = [];
  //----------------------------------------------------------------------------
  var $Request = '';
  //----------------------------------------------------------------------------
  for(var $i in $Args){
    //--------------------------------------------------------------------------
    var $Arg = $Args[$i];
    //--------------------------------------------------------------------------
    if(!['object','string','number'].IsExists(typeof $Arg))
      continue;
    //--------------------------------------------------------------------------
    var $Variable = SPrintF('%s=%s',(typeof $Arg != 'object'?$i:$Arg.Name),encodeURIComponent(typeof $Arg != 'object'?$Arg:$Arg.Value));
    //--------------------------------------------------------------------------
    Debug(SPrintF('Формируем параметр (%s)',$Variable));
    //--------------------------------------------------------------------------
    $Request += $Variable+'&';
  }
  //----------------------------------------------------------------------------
  $Request += 'XMLHttpRequest=yes';
  //----------------------------------------------------------------------------
  Debug(SPrintF('Осуществлям запрос (%s)',$Url));
  //----------------------------------------------------------------------------
  var $Resource = this.Resource;
  //----------------------------------------------------------------------------
  $Resource.open('POST',$Url,true);
  $Resource.onreadystatechange = new Function(SPrintF("if(typeof($Links) != 'undefined') $Links['%s'].Loading();",this.LinkID));
  //----------------------------------------------------------------------------
  try{
    $Resource.setRequestHeader('Method','POST URL HTTP/1.1');
    $Resource.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=utf-8');
  }catch(Exception){
    //--------------------------------------------------------------------------
    Debug('[HTTP::Send]: не удалось установить заголовки запроса');
    //--------------------------------------------------------------------------
    return false;
  }
  //----------------------------------------------------------------------------
  $Resource.send($Request);
  //----------------------------------------------------------------------------
  this.IsFree = false;
  //----------------------------------------------------------------------------
  return true;
};
//------------------------------------------------------------------------------
HTTP.prototype.Loading = function(){
  //----------------------------------------------------------------------------
  if(!this.IsCreated()){
    //--------------------------------------------------------------------------
    alert('Нет HTTP соединения');
    //--------------------------------------------------------------------------
    return false;
  }
  //----------------------------------------------------------------------------
  var $Resource = this.Resource;
  //----------------------------------------------------------------------------
  var $readyState = $Resource.readyState;
  //----------------------------------------------------------------------------
  SetProgress($readyState,4);
  //----------------------------------------------------------------------------
  if($readyState == 4){
    //--------------------------------------------------------------------------
    try{
      var $Status = $Resource.status;
    }catch(Exeption){
      return true;
    }
    //--------------------------------------------------------------------------
    this.onLoaded();
    //--------------------------------------------------------------------------
    switch($Status){
      case 200:
        //----------------------------------------------------------------------
        $responseText = $Resource.responseText;
        //----------------------------------------------------------------------
        if($responseText){
          //--------------------------------------------------------------------
          Debug($responseText);
          //--------------------------------------------------------------------
          $Object = JSON_Decode($responseText);
          if(!$Object){
            //------------------------------------------------------------------
            Debug('Неверный ответ от сервера. Возможно на стороне сервера произошла критическая ошибка.');
            //------------------------------------------------------------------
            this.onError();
          }else
            this.onAnswer($Object);
        }else
          Debug('Пустой ответ от сервера');
      break;
      case 404:
        alert('Запрошенный адрес не существует');
      break;
      default:
        Debug(SPrintF('Сервер вернул код ошибки (%u)',$Status));
    }
    //--------------------------------------------------------------------------
    this.IsFree = true;
    //--------------------------------------------------------------------------
    if(this.Stack.length > 0){
      //------------------------------------------------------------------------
      var $Request = this.Stack[0];
      //------------------------------------------------------------------------
      if(!this.Send($Request.Url,$Request.Args))
        Debug('Не удалось отправить запрос на сервер из стека');
      //------------------------------------------------------------------------
      this.Stack.shift();
    }
  }
};
//------------------------------------------------------------------------------
HTTP.prototype.onLoaded = function(){
  //----------------------------------------------------------------------------
  // Srcipt...
};
//------------------------------------------------------------------------------
HTTP.prototype.onError = function(){
  //----------------------------------------------------------------------------
  // Srcipt...
};
//------------------------------------------------------------------------------
HTTP.prototype.onAnswer = function($Answer){
  //----------------------------------------------------------------------------
  alert($Answer);
};
//------------------------------------------------------------------------------
function AjaxCall($Url,$Args,$Message,$Eval){
  //----------------------------------------------------------------------------
  var $HTTP = new HTTP();
  //----------------------------------------------------------------------------
  if(!$HTTP.Resource){
    //--------------------------------------------------------------------------
    alert('Не удалось создать HTTP соединение');
    //--------------------------------------------------------------------------
    return false;
  }
  //----------------------------------------------------------------------------
  $HTTP.onLoaded = function(){
    //--------------------------------------------------------------------------
    HideProgress();
  }
  //----------------------------------------------------------------------------
  $HTTP.onAnswer = function($Answer){
    //--------------------------------------------------------------------------
    switch($Answer.Status){
      case 'Error':
        ShowAlert($Answer.Error.String,'Warning');
      break;
      case 'Exception':
        ShowAlert(ExceptionsStack($Answer.Exception),'Warning');
      break;
      case 'Ok':
        //----------------------------------------------------------------------
        if($Eval)
          eval($Eval);
      break;
      default:
        alert('Не известный ответ');
    }
  };
  //----------------------------------------------------------------------------
  if(!$HTTP.Send($Url,$Args)){
    //--------------------------------------------------------------------------
    alert('Не удалось отправить запрос на сервер');
    //--------------------------------------------------------------------------
    return false;
  }
  //----------------------------------------------------------------------------
  ShowProgress($Message);
}