// JsHttpRequest Class
var JsHttpRequest = {
  handlers : [],
  handlersCounter : 0,
  timeouts : [],
  headNode : undefined,
  scriptTagIdPref : "JsHttpRequest_",


// Public methods

////
  request : function ( options ) {

    if ( !options ) {
      throw( "Request options not specified" );
    }
    else if ( !options.hooks || !options.hooks.oncomplete ) {
      throw( "Request handler not specified" );
    }
    else if ( !options.uri ) {
      throw( "Request URI not specified" );
    }

    handlerId = JsHttpRequest.handlersCounter++;

    if ( options.hooks.onloading ) {
      options.hooks.onloading();
    }

    options.uri += "?";

    if ( options.parameters ) {
      var joinedParameters = JsHttpRequest.joinParameters( options.parameters );

      if ( joinedParameters ) {
        options.uri += joinedParameters + "&";
      }
    }

    options.uri += "__hid=" + handlerId + "&__rand=" + Math.random();

    JsHttpRequest.makeHandler( handlerId, options.hooks.oncomplete );
    JsHttpRequest.createScriptTag( handlerId, options.uri );

    if ( options.timeout 
        && options.hooks.onabort ) {
      
      var abortHandler = function() { 
        JsHttpRequest.abort( handlerId, options.hooks.onabort ); 
      };

      JsHttpRequest.timeouts[ handlerId ] 
          = setTimeout( abortHandler, options.timeout );
    }

    return 1;
  },


// Private methods

////
  joinParameters : function ( parameters ) {
    var joinedParameters = "";  
    var isFirst = true;

    for ( name in parameters ) {
      var value = parameters[ name ];

      if ( !isFirst ) {
        joinedParameters += "&";    
      }
      else {
        isFirst = false;
      }

      if ( typeof( value ) == "object" ) {
        
        if ( value instanceof Array ) {

          for ( var i = 0; i < value.length; i++ ) {

            if ( i > 0 ) {
              joinedParameters += "&";
            }

            joinedParameters += name + "=" + encodeURIComponent( value[ i ] );
          }
        }
      }
      else {
        joinedParameters += name + "=";

        if ( parameters[ name ] != undefined ) {
          joinedParameters += encodeURIComponent( parameters[ name ] );
        }
      }
    }
    
    return joinedParameters;
  },

////
  makeHandler : function ( handlerId, userHandler ) {

    var handler = function( data ) { 
      JsHttpRequest.removeScriptTag( handlerId );

      if ( JsHttpRequest.timeouts[ handlerId ] ) {
        clearTimeout( JsHttpRequest.timeouts[ handlerId ] );
      }

      userHandler( data );
    };

    JsHttpRequest.handlers[ handlerId ] = handler;

    return 1;
  },

////
  createScriptTag : function ( handlerId, uri ) {
    var script = window.document.createElement( "script" );
    script.id = JsHttpRequest.scriptTagIdPref + handlerId;
    script.type = "text/javascript";
    script.src = uri;
    
    if ( !JsHttpRequest.headNode ) {
      var elements = window.document.getElementsByTagName( "head" );
      JsHttpRequest.headNode = elements[ 0 ];
    }

    JsHttpRequest.headNode.appendChild( script );

    return 1;
  },

////
  removeScriptTag : function ( handlerId ) {
    
    if ( JsHttpRequest.headNode ) {
      var script = window.document.getElementById( 
          JsHttpRequest.scriptTagIdPref + handlerId );
      JsHttpRequest.headNode.removeChild( script );
    }

    return 1;
  },

////
  abort : function ( handlerId, handler ) {
    
    if ( handler ) {
      handler();
    }

    return 1;
  }
};


// Class Hiro
var Hiro = {
  mainWrap : undefined,
  headNode : undefined,
  subPartnerId : undefined,

  baseUri : "http://hiro.smsonline.ru/",
  partnerUri : undefined,
  currentUri : undefined,
  smsWorldUri : "http://rate.smsonline.ru/r.cgi",
  smsLockUri : "http://s077.smsonline.ru/",
  
  char : {
    serviceId : "10002",
    prefix : "141",
    price : "150"
  },

  destiny : {
    serviceId : "10001",
    prefix : "140",
    price : "150"
  },

  onChangeUriIsActive : true,
  smsCodeCheckerInterval : undefined,

////
  init : function ( section ) {
    var hash = window.location.hash;
    var typeTest;
    
    if ( section && ( section == "character" ) ) {
      typeTest = true;
    }
    else {
      typeTest = false;
    }

    if ( hash.indexOf( "#hiro/" ) == 0 ) {
      var paramsStr = hash.substr( 6 );
      var params = Hiro.getParams( paramsStr );

      if ( typeTest ) {
        params[ "t" ] = "fl";
      }

      Hiro.request( params );
    }
    else {

      if ( typeTest ) {
        var params = {};
        params[ "t" ] = "fl";

        Hiro.request( params );
      }
      else {
        Hiro.request();
      }
    }

    return 1;
  },

////
  attachCss : function () {
    var link = window.document.createElement( "link" );
    link.rel = "stylesheet";
    link.type = "text/css";
    link.href = Hiro.baseUri + "?a=css";
    
    if ( HiroOptions.skin ) {
      link.href += "&sk=" + HiroOptions.skin;
    }

    Hiro.headNode.appendChild( link );
    
    return 1;
  },

////
  getParams : function ( paramsStr ) {
    var params = {};
    var pairs = paramsStr.split( ";" );

    for ( var i = 0; i < pairs.length; i++ ) {
      var tokens = pairs[ i ].split( "=" );
      var name = tokens[ 0 ];
      var value = tokens[ 1 ];

      if ( value ) {

        if ( params[ name ] ) {
          
          if ( typeof( params[ name ] ) != "object" ) {
            var val = params[ name ];
            params[ tokens[ 0 ] ] = new Array;
            params[ tokens[ 0 ] ][ 0 ] = val;
          }
    
          params[ name ].push( value );
        }
        else {
          params[ name ] = value;
        }
      }
    }
  
    return params;
  },

////
  onChangeUri : function () {
   
    if ( Hiro.onChangeUriIsActive && Hiro.currentUri 
        && ( Hiro.currentUri != window.location.href ) ) {

      Hiro.currentUri = window.location.href;
      var hash = window.location.hash;

      if ( hash.indexOf( "#hiro/" ) == 0 ) {
        var paramsStr = hash.substr( 6 );
        var params = Hiro.getParams( paramsStr );
        Hiro.request( params );
      }
      
      return 1;
    }
    
    Hiro.onChangeUriIsActive = true;
    Hiro.currentUri = window.location.href;

    return 1;
  },

////
  submitMainForm : function ( evt, form ) {
    Hiro.preventDefault( evt );
    var params = Hiro.getParametersFromForm( form );

    errors = Hiro.checkMainFormParameters( params );
//   errors = undefined;
    if ( errors ) {
      var errMsg = new Array;
      
      if ( errors[ "missingUser" ] ) {
        errMsg.push( "Вы не назвали свое имя." );
      }

      if ( errors[ "missingEmail" ] ) {
        errMsg.push( "Вы не ввели адрес электронной почты." );
      }
      else if ( errors[ "invalidEmail" ] ) {
        errMsg.push( "Вы указали неверный адрес электронной почты." );
      }

      if ( errors[ "missingFingers" ] ) {
        errMsg.push( "Вы выбрали не все пальцы." );
      }

      Hiro.showErrMsg( "Вы указали не все необходимые данные:", errMsg );
//      Hiro.request( params );
    }
    else {
      Hiro.request( params );
    }

    return 1;
  },

////
  checkMainFormParameters : function ( params ) {
    var errors = {};
    var wrongInput = false;
    var fingersNum = 0;
      
    if ( !params[ "user" ] ) {
      errors[ "missingUser" ] = 1;

      if ( !wrongInput ) {
        wrongInput = true;
      }
    }
    
    if ( !params[ "email" ] ) {
      errors[ "missingEmail" ] = 1;
      
      if ( !wrongInput ) {
        wrongInput = true;
      }
    }
    else if ( !params[ "email" ].match( /^([a-zA-Z0-9_'+*$%\^&!\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9:]{2,4})+$/ ) ) {
      errors[ "invalidEmail" ] = 1;
      
      if ( !wrongInput ) {
        wrongInput = true;
      }
    }

    for ( pname in params ) {
      
      if ( pname.match( /^f\d/ ) ) {
        fingersNum++;
      }
    }
    
    if ( fingersNum < 10 ) {
      errors[ "missingFingers" ] = 1;

      if ( !wrongInput ) {
        wrongInput = true;
      }
    }

    if ( wrongInput ) {
      return errors;
    }

    return undefined;
  },

////
  submitUnlockForm : function ( evt, form ) {
    Hiro.preventDefault( evt );

    var params = Hiro.getParametersFromForm( form );

    if ( params[ "passw" ] ) {
      params[ "a" ] = "chp";
      params[ "idp" ] = Hiro.partnerId;

      var typeTest = params[ "t" ] ? true : false;

      var handler = function( data ) {
        Hiro.unlockByPassword( typeTest, params[ "passw" ], data );
      };

      JsHttpRequest.request( {
          hooks : { 
              onloading : Hiro.showProgressBar,
              oncomplete : handler
            },
          
          parameters : params,
          uri : Hiro.baseUri
        } );
    }
    else {
      Hiro.showErrMsg( "Ошибка!", "Вам нужно указать пароль, полученный в СМС." );
    }

    return 1;
  },

////
  submit : function ( evt, form ) {
    Hiro.preventDefault( evt );
    var params = Hiro.getParametersFromForm( form );
    Hiro.request( params );

    return 1;
  },

////
  getParametersFromForm : function ( form ) {
    var params = {};

    for ( var i = 0; i < form.elements.length; i++ ) {
      var element = form.elements[ i ];

      if ( ( element.type == "checkbox" ) 
            || ( element.type == "radio" ) ) {

         if ( element.checked ) {
            params[ element.name ] = element.value;
         }
      }
      else if ( element.type == "select" ) {
        params[ element.name ] = element.options[ element.selectedIndex ];
      }
      else if ( element.value ) {
        params[ element.name ] = element.value;
      }
    }

    return params;
  },

////
  request : function ( params ) {

    if ( !params ) {
      params = {};
    }
    
    params[ "idp" ] = Hiro.partnerId;

    if ( HiroOptions ) {

      if ( HiroOptions.skin ){
        params[ "sk" ] = HiroOptions.skin;
      }

      if ( HiroOptions.unicode ){
        params[ "u" ] = 1;
      }
    }
    
    JsHttpRequest.request( {
        hooks : { 
            onloading : Hiro.showProgressBar,
            oncomplete : Hiro.outputContent
          },
        
        parameters : params,
        uri : Hiro.baseUri
      } );

    return 1;
  },

////
  showProgressBar : function () {
    var shadowWrap = window.document.createElement( "div" );
    shadowWrap.id = "HiroShadowWrap";
    var progressBar = window.document.createElement( "div" );
    progressBar.id = "HiroProgressBar";
    Hiro.mainWrap.appendChild( shadowWrap ); 
    Hiro.mainWrap.appendChild( progressBar ); 
  },

////
  outputContent : function ( data ) {
    Hiro.mainWrap.innerHTML = data;
    var pos = Hiro.getAbsolutePos( Hiro.mainWrap );
    window.scroll( 0, pos.y );

// Handle macros
    inputs = Hiro.mainWrap.getElementsByTagName( "input" );

    for ( var i = 0; i < inputs.length; i++ ) {
      var input = inputs[ i ];

      if ( ( input.type == "hidden" ) 
          && ( input.id.match( /^HiroMacros/ ) ) ) {
      
        eval( input.value );
      }
    }

    return 1;
  },

////
  getEvent : function ( evt ) {
    return evt ? evt : window.event;
  },

////
	preventDefault : function ( evt ){
		evt = Hiro.getEvent( evt );

		if ( evt ) {

			if( evt.preventDefault ){
				evt.preventDefault();
			}
			else{
			  evt.returnValue = false;
			}
		}

    return 1;
	},

////
	addEventListener : function ( node, eventType, handler ){

		if ( node.attachEvent ) {
			node.attachEvent( "on" + eventType, handler );
		}
		else if ( node.addEventListener ) {
			node.addEventListener( eventType, handler, false );
		}
	},

////
	removeEventListener : function ( node, eventType, handler ){

		if ( node.detachEvent ) {
			node.detachEvent( "on" + eventType, handler );
		}
		else if ( node.removeEventListener ) {
			node.removeEventListener( eventType, handler, false );
		}

    return 1;
	},


////
  loadSmsWorld : function ( typeTest, smscode ) {

    if ( typeTest ) {
      soOptions.pref = Hiro.char.prefix;
      soOptions.price = Hiro.char.price;
      soOptions.msg = "Чтобы получить описание Вашего характера, отправьте SMS с кодом %t на номер %sn";
    }
    else {
      soOptions.pref = Hiro.destiny.prefix;
      soOptions.price = Hiro.destiny.price;
      soOptions.msg = "Чтобы получить определение Вашей судьбы, отправьте SMS с кодом %t на номер %sn";
    }
    
    soOptions.txt = smscode;

    var scriptUri = Hiro.smsWorldUri
        + "?pid=" + ( soOptions.partnerid ? soOptions.partnerid : "" )
        + "&pref=" + ( soOptions.pref ? soOptions.pref : "" )
        + "&u=" + ( soOptions.unicode ? 1 : 0 )
        + "&l=" + ( soOptions.lang ? soOptions.lang : "ru" )
        + "&psr=" + ( soOptions.psr ? soOptions.psr : "" )
        + "&prc=" + ( soOptions.price ? soOptions.price : "" );

    var script = window.document.createElement( "script" );
    script.type = "text/javascript";
    script.src = scriptUri;
    Hiro.headNode.appendChild( script );

    if ( smscode ) {

      var handler = function () { 
        Hiro.smsCodeChecker( typeTest, smscode );
      };

      Hiro.smsCodeCheckerInterval = setInterval( handler,  5000 );
    }

    return 1;
  },

////
  smsCodeChecker : function ( typeTest, smscode ) {
    var serviceId = typeTest ? Hiro.char.serviceId : Hiro.destiny.serviceId;
    
    var params = {
      "a" : "check",
      "idp" : Hiro.partnerId,
      "sid" : serviceId,
      "code" : smscode
    };

    var handler = function ( data ) { 
      Hiro.unlockBySmsCode( typeTest, smscode, data ) 
    };

    JsHttpRequest.request( {
        hooks : { 
            oncomplete : handler
          },
        
        parameters : params,
        uri : Hiro.smsLockUri
      } );

    return 1;
  },

////
  unlockBySmsCode : function ( typeTest, smscode, data ) {
   
    if ( data && !data.match( /^\d+$/ ) ) {
      clearInterval( Hiro.smsCodeCheckerInterval );

      var params = {
          "a" : "vr",
          "smsc" : smscode
        };

      if ( typeTest ) {  
        params[ "t" ] = "fl";
      }

      Hiro.onChangeUriIsActive = false;
      var href = "#hiro/a=vr";

      if ( typeTest ) {
        href += ";t=fl";
      }
      
      window.location.href = href;
      Hiro.request( params );
    }

    return 1;
  },

////
  unlockByPassword : function ( typeTest, passw, data ) {
    var shadowWrap = window.document.getElementById( "HiroShadowWrap" );
    var progressBar = window.document.getElementById( "HiroProgressBar" );
    Hiro.mainWrap.removeChild( shadowWrap ); 
    Hiro.mainWrap.removeChild( progressBar ); 

    if ( data && data != "0" ) {
      clearInterval( Hiro.smsCodeCheckerInterval );

      var params = {
          "a" : "vr",
          "passw" : passw
        };

      if ( typeTest ) {  
        params[ "t" ] = "fl";
      }

      Hiro.onChangeUriIsActive = false;
      var href = "#hiro/a=vr";

      if ( typeTest ) {
        href += ";t=fl";
      }
      
      window.location.href = href;
      Hiro.request( params );
    }
    else {
      Hiro.showErrMsg( "Ошибка!", "Введенный Вами пароль не подходит для данного сервиса, либо Вы ошиблись при вводе. Убедитесь в соответствии пароля, полученного в СМС, и попробуйте еще раз." );
    }

    return 1;
  },

////
    showErrMsg : function ( errHeader, errMsg ) {
    var hiroWrap = window.document.getElementById( "HiroWrap" );
    var shadowWrap = window.document.createElement( "div" );
    shadowWrap.id = "HiroShadowWrap";

    var errWrap = window.document.createElement( "div" );
    errWrap.id = "HiroErrWrap";

    var errHtml = "<div class=\"star_wrap\"><div class=\"lt_err\"></div><div class=\"lb_err\"></div><div class=\"rt_err\"></div><div class=\"rb_err\"></div><div class=\"lv_err\"></div><div class=\"rv_err\"></div><div class=\"th_err\"></div><div class=\"title_err txt_err\">";
    
    if ( errHeader ) {
      errHtml += "<h3>" + errHeader + "</h3>";
    }
    
    errHtml += "<ul>";

    if ( ( typeof( errMsg ) == "object" ) 
        && ( errMsg instanceof Array ) ) {
    
      for ( var i = 0; i < errMsg.length; i++ ) {
        errHtml += "<li>" + errMsg[ i ] + "</li>";
      }
    }
    else {
      errHtml += "<li>" + errMsg + "</li>";
    }

    errHtml += "</ul><div class=\"centerx\"><div class=\"centery\"><input id=\"HiroButton\" type=\"button\" value=\"&nbsp;&nbsp;&nbsp;ОК&nbsp;&nbsp;&nbsp;\" onclick=\"Hiro.removeErrMsg()\" /></div></div></div><div class=\"bh_err\"></div></div>";

    errWrap.innerHTML = errHtml;


    hiroWrap.appendChild( shadowWrap ); 
    hiroWrap.appendChild( errWrap ); 

    Hiro.focusButton();

  },

////
  removeErrMsg : function () {
    var shadowWrap = window.document.getElementById( "HiroShadowWrap" );
    var errWrap = window.document.getElementById( "HiroErrWrap" );

    var parentWrap = shadowWrap.parentNode;
    parentWrap.removeChild( shadowWrap );
    parentWrap.removeChild( errWrap );
  },

////
  focusButton : function () {
    button = window.document.getElementById( "HiroButton" );
    button.focus();

    return 1;
  },

////
	openWindow : function( evt, uri, width, height ) {
    smsWorld.preventDefaultAction( evt );
    
		var screenx = ( screen.width - width ) / 2;

		var winOpt = "toolbar=0,scrollbars=yes";
    
    if ( width ) {
      winOpt += ",width=" + width;
    }
    
    if ( height ) {
      winOpt += ",height=" + height;
    }
    
    winOpt += ",personalbar=0,menubar=0,location=0" 
        + ",personalbar=0,resizable=0,left=" + screenx;

		window.open( uri, '', winOpt );
	},

////
  determinePartnerId : function () {
    
    if ( HiroOptions.partnerId ) {
      Hiro.partnerId = HiroOptions.partnerId;
    }
    else {
      var search = window.location.search;

      if ( search.match( /[?&]idp=(\d+)/ ) ) {
        Hiro.partnerId = RegExp.$1;
      }
      else {
        Hiro.partnerId = 1;
      }
    }
  },

////
  getAbsolutePos : function ( node ) {
    var pos = { x : node.offsetLeft, y : node.offsetTop };

    if ( node.offsetParent ) {
      var tmp = Hiro.getAbsolutePos( node.offsetParent );
      pos.x += tmp.x;
      pos.y += tmp.y;
    }

    return pos;
  },

////
  changeTest : function ( selectField ) {
    var selectedIndex = selectField.selectedIndex;
    var value = selectField.options[ selectedIndex ].value;

    window.location.href = value;
    
    return 1;
  },

////
  changeBackground : function ( typeTest ) {
    
    if ( !HiroOptions.partnerId ) {
      var wrap = window.document.getElementById( "HiroBgWrap" );

      if ( wrap ) {

        if ( typeTest && ( wrap.className == "bg2" ) ) {
          wrap.className = "bg1";
        }
        else if ( !typeTest && ( wrap.className == "bg1" ) ) {
          wrap.className = "bg2";
        }
      }
    }

    return 1;
  }
};


// SMSWorld options
var soOptions = {
  partnerid: 1,
  pref: undefined,
  join: true,
  price: undefined,
  psr: "near",
  msg: undefined,
  info: "[Информация о стоимости услуги]",
  skin: "simple",
  lang: "ru",
  unicode: HiroOptions.unicode,
  lock: true,
  markup: "manual"
};


// Main
Hiro.determinePartnerId();
Hiro.mainWrap = window.document.getElementById( "Hiro" ).parentNode;
Hiro.headNode = window.document.getElementsByTagName( "head" )[ 0 ];

Hiro.partnerUri = window.location.href;
Hiro.partnerUri = Hiro.partnerUri.replace( /#.*$/, "" );
Hiro.currentUri = window.location.href;

setInterval( Hiro.onChangeUri, 1 );

Hiro.attachCss();
Hiro.init( HiroOptions.section );
