// ================================================================================
// ================================================================================
// PIN*PAD                           (c) 1997-2004 Kleeton PL - ianbrown@msn.com.au
// ================================================================================
// ================================================================================




// ===========
// initialise
// ===========

// create pinpad by generating html.
// store obj-refs to element-objects or related style-objects.


  var pinpad_logo, target_url;

  var pinpad_FOLDER       = 'xpinpad';            // MUST BE SET (relative to calling page)
  var pinpad_PAGE_PREFIX  = 'pin_';
  var pinpad_PAGE_EXT     = 'htm';

  var pinpad_TARGET_IN_NEW_WINDOW  = true;        // open-mode for target page
  var pinpad_AUTOHIDE_TIMEOUT      = 30;          // inactivity duration to activate autohide (seconds)

  var xLCD         = '';
  var xPIN         = '';
  var pinpad_logo  = '<span style="font-size:70%; color:#0000C0; letter-spacing:4px; ' +
                                    'behavior:url(' + pinpad_FOLDER + '/sys/hue.htc);">pin*pad</span>';


  pinpad_create();



  var oPinpad_style      = window.document.getElementById('pinpad').style;
  var oLCD               = window.document.getElementById('lcd');

  var oKeysNumbrs1_style = window.document.getElementById('keyrow_numbrs1').style;
  var oKeysNumbrs2_style = window.document.getElementById('keyrow_numbrs2').style;
  var oKeysNumbrs3_style = window.document.getElementById('keyrow_numbrs3').style;
  var oKeysNumbrs4_style = window.document.getElementById('keyrow_numbrs4').style;
  var oKeysAlphas1_style = window.document.getElementById('keyrow_alphas1').style;
  var oKeysAlphas2_style = window.document.getElementById('keyrow_alphas2').style;
  var oKeysAlphas3_style = window.document.getElementById('keyrow_alphas3').style;
  var oKeysAlphas4_style = window.document.getElementById('keyrow_alphas4').style;

  pinpad_lcd_mode_logo();






// ===========
// METHODS
// ===========



  // create user-interface html structures (initially hidden from user)

  function pinpad_create()
  {
    var lcdStyle, butStyle, panelOuterStyle, panelMiddleStyle, panelInnerStyle, htmlText;

    lcdStyle         = ' style="font-size: 107%; width: 100%; border: 2px inset #bbc;'     +
                              'height: 17px; line-height: 120%; letter-spacing: 0.02em;'   +
                              'font-weight: bold; color: #C00000; background-color: #eec;' +
                              'cursor: all-scroll; cursor: move;" ';

    butStyle         = ' style="width: 52px; height: 30px; cursor: pointer; letter-spacing: 2px;'   +
                              'font-family: Verdana; font-size: 14px; font-weight: bold;" ';

    panelOuterStyle  = ' style="background-color:#aaa; padding:0px; margin: 10px; border: 8px solid #d0d0e0;" ';
    panelMiddleStyle = ' style="background-color:#666; border: 3px inset #bbc; padding: 6px; margin: 0px;" ';
    panelInnerStyle  = ' style="text-align: center; background: #999; border: 2px outset #fff;" ';

    htmlText =
      '<div id="xpinpad" style="padding:6em 0px;">' +
      '  <table '           + panelOuterStyle  +  ' cellpadding="0" cellspacing="0" border="0">' +
      '   <tr>' +
      '    <td>' +
      '      <table '       + panelMiddleStyle +  ' cellpadding="0" cellspacing="0" border="0">' +
      '       <tr>' +
      '        <td>' +
      '          <form                              style="padding:0; margin:0; border:0;">'     +
      '            <table ' + panelInnerStyle  +  ' cellpadding="1" cellspacing="2" border="0">' +
      '                <tr onmouseover="pinpad_lcd_hoveron()" onmouseout="pinpad_lcd_hoveroff()" title="click to flip keypads">' +
      '                    <td colspan=3><span id="lcd" onclick="pinpad_keypads_swap();" title="click to flip keypads" '  + lcdStyle +  '></span></td>' +
      '                </tr>' +
      '                <tr id="keyrow_numbrs1">'  +
      '                    <td><input type=button  value=" 1 "  onclick="pinpad_keypress(1)"  '  + butStyle +  '></td>' +
      '                    <td><input type=button  value=" 2 "  onclick="pinpad_keypress(2)"  '  + butStyle +  '></td>' +
      '                    <td><input type=button  value=" 3 "  onclick="pinpad_keypress(3)"  '  + butStyle +  '></td>' +
      '                </tr>' +
      '                <tr id="keyrow_numbrs2">'  +
      '                    <td><input type=button  value=" 4 "  onclick="pinpad_keypress(4)"  '  + butStyle +  '></td>' +
      '                    <td><input type=button  value=" 5 "  onclick="pinpad_keypress(5)"  '  + butStyle +  '></td>' +
      '                    <td><input type=button  value=" 6 "  onclick="pinpad_keypress(6)"  '  + butStyle +  '></td>' +
      '                </tr>' +
      '                <tr id="keyrow_numbrs3">'  +
      '                    <td><input type=button  value=" 7 "  onclick="pinpad_keypress(7)"  '  + butStyle +  '></td>' +
      '                    <td><input type=button  value=" 8 "  onclick="pinpad_keypress(8)"  '  + butStyle +  '></td>' +
      '                    <td><input type=button  value=" 9 "  onclick="pinpad_keypress(9)"  '  + butStyle +  '></td>' +
      '                </tr>' +
      '                <tr id="keyrow_numbrs4">'  +
      '                    <td><input type=button  value=" * "  onclick="pinpad_asterisk();"  '  + butStyle +  ' title="show help, or, clear PIN"></td>' +
      '                    <td><input type=button  value=" 0 "  onclick="pinpad_keypress(0)"  '  + butStyle +  '></td>' +
      '                    <td><input type=button  value=" # "  onclick="pinpad_processPIN()" '  + butStyle +  ' title="send PIN"></td>' +
      '                </tr>' +
      '                <tr id="keyrow_alphas1" style="display:none">'  +
      '                    <td><input type=button  value="qz"   onclick="pinpad_keypress(1)"  '  + butStyle +  '></td>' +
      '                    <td><input type=button  value="abc"  onclick="pinpad_keypress(2)"  '  + butStyle +  '></td>' +
      '                    <td><input type=button  value="def"  onclick="pinpad_keypress(3)"  '  + butStyle +  '></td>' +
      '                </tr>' +
      '                <tr id="keyrow_alphas2" style="display:none">'  +
      '                    <td><input type=button  value="ghi"  onclick="pinpad_keypress(4)"  '  + butStyle +  '></td>' +
      '                    <td><input type=button  value="jkl"  onclick="pinpad_keypress(5)"  '  + butStyle +  '></td>' +
      '                    <td><input type=button  value="mno"  onclick="pinpad_keypress(6)"  '  + butStyle +  '></td>' +
      '                </tr>' +
      '                <tr id="keyrow_alphas3" style="display:none">'  +
      '                    <td><input type=button  value="prs"  onclick="pinpad_keypress(7)"  '  + butStyle +  '></td>' +
      '                    <td><input type=button  value="tuv"  onclick="pinpad_keypress(8)"  '  + butStyle +  '></td>' +
      '                    <td><input type=button  value="wxy"  onclick="pinpad_keypress(9)"  '  + butStyle +  '></td>' +
      '                </tr>' +
      '                <tr id="keyrow_alphas4" style="display:none">'  +
      '                    <td><input type=button  value=" * "  onclick="pinpad_asterisk();"  '  + butStyle +  ' title="show help, or, clear PIN"></td>' +
      '                    <td><input type=button  value="[ ]"  onclick="pinpad_keypress(0)"  '  + butStyle +  ' title="space-bar"></td>' +
      '                    <td><input type=button  value=" # "  onclick="pinpad_processPIN()" '  + butStyle +  ' title="send PIN"></td>' +
      '                </tr>' +
      '            </table>'  +
      '          </form>' +
      '        </td>' +
      '       </tr>' +
      '      </table>' +
      '    </td>' +
      '   </tr>' +
      '  </table>' +
      '</div>';
    document.write(htmlText);
  }



  // display numeric and alphabetic keypads

  function pinpad_keypads_swap()
  {
       pinpad_userActivity_handler(null);
      if ( oKeysNumbrs1_style.display != 'none' )
      {
          pinpad_keypads_alphabetic();
      }
      else
      {
          pinpad_keypads_numeric();
      }
  }

  function pinpad_keypads_numeric()
  {
      oKeysNumbrs1_style.display = 'block';
      oKeysNumbrs2_style.display = 'block';
      oKeysNumbrs3_style.display = 'block';
      oKeysNumbrs4_style.display = 'block';
      oKeysAlphas1_style.display = 'none';
      oKeysAlphas2_style.display = 'none';
      oKeysAlphas3_style.display = 'none';
      oKeysAlphas4_style.display = 'none';
  }

  function pinpad_keypads_alphabetic()
  {
      oKeysAlphas1_style.display = 'block';
      oKeysAlphas2_style.display = 'block';
      oKeysAlphas3_style.display = 'block';
      oKeysAlphas4_style.display = 'block';
      oKeysNumbrs1_style.display = 'none';
      oKeysNumbrs2_style.display = 'none';
      oKeysNumbrs3_style.display = 'none';
      oKeysNumbrs4_style.display = 'none';
  }




  // show &  hide pinpad

  function pinpad_show()
  {
    pinpad_clear();
    pinpad_keypads_numeric();
    oPinpad_style.display='block';
    pinpad_userActivity_handler(null);
 }

  function pinpad_hide()
  {
   // oPinpad_style.display='none';
  }



  // process key-presses :: store user PIN chars

  function pinpad_keypress(keynum)
  {
    pinpad_userActivity_handler(keynum);
    oLCD.style.backgroundColor='#ffb';
    xPIN       += keynum;
    xLCD       += "*";
    oLCD.innerHTML = xLCD;
  }


  // process user PIN :: user pressed '#'

  function pinpad_processPIN()
  {
      pinpad_autohide_killTimer();
      if ( pinpad_haveUserPIN() )
      {
          if ( xPIN == '0' || xPIN == '746723' || xPIN == '4357' )           //  '0' (or spacebar),   'help'  or  'pinpad'
          {
              target_url = pinpad_FOLDER + '/sys/pinpad_about.htm';
              pinpad_load_url(target_url);
          }
          else
          {
              target_url = pinpad_FOLDER + '/'+ pinpad_PAGE_PREFIX + xPIN + '.' + pinpad_PAGE_EXT;
              pinpad_process_url();
          }
      }
      else
      {
          pinpad_lcd_mode_logo();
          pinpad_hide();                                                    // no pin - exit
      }
  }

  function pinpad_processPIN_callback(http_status)
  {
      var ERROR_MSG;
      ERROR_MSG =  'pin*pad access manager\n'    +
                   '____________________\n\n\n'  +
                   'the PIN you entered may be invalid,\n'      +
                   'or network/system problems have occurred.\n\n\n'                  +
                   'prior authorisation is mandatory for access.\n\n\n'               +
                   'if problems persist, please contact our web-administrator.\n\n'   +
                   'please enter your PIN again';

      if ( http_status == pinpad_URL_EXISTS_REMOTE || http_status == pinpad_URL_EXISTS_LOCAL )
      {
         pinpad_load_url(target_url);
      }
      else
      {
          pinpad_autohide_killTimer();
          window.alert(ERROR_MSG);
          pinpad_userActivity_handler(null);
          pinpad_clear();
      }
  }

  // load resolved url

  function pinpad_load_url(url)
  {
      pinpad_lcd_mode_logo();
      pinpad_hide();
      if ( istrue(pinpad_TARGET_IN_NEW_WINDOW) )
      {
          window.open(url,"","")
      }
      else
      {
          window.location.href = url;
      }
}




  // process "*" keypress :: help OR clear

  function pinpad_asterisk()
  {
      pinpad_userActivity_handler('*');
      if ( pinpad_haveUserPIN() )
      {
        pinpad_clear();
      }
      else
      {
        pinpad_help();
      }
  }



  // reset pinpad :: clear all (lcd, pin, etc)

  function pinpad_clear()
  {
      pinpad_lcd_mode_logo();
      xPIN = '';
      xLCD = '';
  }


  // display help as dialog-box

  function pinpad_help()
  {
    var msg;
    msg = 'pin * pad      ::::      first-choice in security      ::::      (c) kleeton pl\n' +
          '___________________________________________________\n\n'         +
          '           R E S T R I C T E D   A R E A   A C C E S S\n\n'      +
          '           e n t e r   P I N   t h e n   c l i c k   [ # ]\n\n'  +
          '           for HELP INFO use PIN "0" or PIN "pinpad".\n'         +
          '           click [display-panel] to flip numbers & letters.\n\n' +
          '           for security, your actions will be monitored\n\n'     +
          '           [ [  e n t e r   y o u r   P I N   s l o w l y  ] ]';
    pinpad_autohide_killTimer();
    window.alert(msg);
    pinpad_userActivity_handler(null);
  }




  // lcd mode :: either logo display, OR, user PIN display

  function pinpad_lcd_mode_logo()
  {
      oLCD.style.backgroundColor='#000';
      oLCD.innerHTML = pinpad_logo;
  }

  function pinpad_lcd_mode_pin()
  {
      oLCD.style.backgroundColor='#eec';
      oLCD.innerHTML = xLCD;
  }




  // determine whether user has commence entering a PIN

  function pinpad_haveUserPIN()
  {
      return  (  (xPIN != '') ? true : false  );
  }



  // user is active, restart inactivity period
  function pinpad_userActivity_handler(keyid)
  {
    pinpad_autohide_startCountdown();
  }



  // lcd hover processiing: change border

  function pinpad_lcd_hoveron()
  {
    pinpad_userActivity_handler(null);
    oLCD.style.borderColor = '#bcd';
    oLCD.style.borderStyle = 'solid';
  }

  function pinpad_lcd_hoveroff()
  {
    pinpad_userActivity_handler(null);
    oLCD.style.borderColor = '#bbc';
    oLCD.style.borderStyle = 'inset';
  }


  // auto-hide on inactivity

  var pinpad_autohide_timerRef = null;

  function pinpad_autohide_startCountdown()
  {
    var MS_PER_SECOND = 1000;
    var timeout_duration = pinpad_AUTOHIDE_TIMEOUT * MS_PER_SECOND;
    pinpad_autohide_killTimer();
    pinpad_autohide_timerRef = window.setTimeout(pinpad_autohide_handleTimeout, timeout_duration);
  }

  function pinpad_autohide_handleTimeout()
  {
      pinpad_autohide_killTimer();
      pinpad_hide();
  }



  function pinpad_autohide_killTimer()
  {
      if ( exists(pinpad_autohide_timerRef) )
      {
          window.clearTimeout(pinpad_autohide_timerRef);
      }
      pinpad_autohide_timerRef = null;
 }




// ================================================================================
// URL EXISTS ? (XMLHttpRequest :: client-calback = pinpad_processPIN_callback)
// ================================================================================


  //  NOTE: the XMLHTTP 'async' parameter seems confusing  (default is False - the call does not return immediately).
  //        try/catch construct required due to error when serving-page from local-storage, instead of an http-server.

  function pinpad_process_url()
  {
      var xmethod   = 'HEAD';         // upper-case            !!!
      var xurl      = target_url;     // absolute or relative
      var xasync    = true;           // true means syc        !!!
      var xuser     = null;
      var xpassword = null;

      if ( exists(pinpad_oXMLHTTP) )
      {
          pinpad_oXMLHTTP.open(xmethod, xurl, xasync, xuser, xpassword);
          pinpad_oXMLHTTP.onreadystatechange = pinpad_process_url_statechange;     // callback

          try
          {
               pinpad_oXMLHTTP.send(null);
          }
          catch (e) {;}
      }
      else
      {
          pinpad_processPIN_callback(pinpad_URL_EXISTS_REMOTE);     //cant check url:  force OK
      }
  }


  function pinpad_process_url_statechange()
  {
      if (pinpad_oXMLHTTP.readyState == pinpad_HTTP_LOADED_OK)
      {
         pinpad_processPIN_callback(pinpad_oXMLHTTP.status);
      }
  }



  // INITIALISE

  var pinpad_URL_EXISTS_LOCAL     = 0;                   // determined empirically   VERFIFY
  var pinpad_URL_EXISTS_REMOTE    = 200;                 // w3c - http1.1
  var pinpad_URL_EXISTSNOT_REMOTE = 404;                 // w3c - http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
  var pinpad_HTTP_LOADED_OK       = 4;                   // w3c

  var pinpad_oXMLHTTP;

  pinpad_XMLHTTPRequest_create();


  // create  object XMLHttpRequest
  // (tricky browser-specific code :: requires different code for each of both versions of msxml and Mozilla)

  function pinpad_XMLHTTPRequest_create()
  {
      // for internet explorer / msxml

      /*@cc_on @*/

      /*@if (@_jscript_version >= 5)
         try
         {
         pinpad_oXMLHTTP = new ActiveXObject("Msxml2.XMLHTTP");                             // try new msxml
         }
         catch (e)
         {
             try
             {
                       pinpad_oXMLHTTP = new ActiveXObject("Microsoft.XMLHTTP");            // try new msxml
             }
             catch (E)
             {
                       pinpad_oXMLHTTP = false;                                             // no msxml available
             }
         }
         @else
         if (!pinpad_oXMLHTTP && document.createElement)
         {
            try
            {
                       pinpad_oXMLHTTP = new XMLHttpRequest();
            }
            catch (e)
            {
                       pinpad_oXMLHTTP=false;                                               // old ie
            }
         }
         @end @*/

        // for other good w3c browsers (Moz, etc)

        var httpobj_not_created_by_ie = !(exists(pinpad_oXMLHTTP));
        var is_modern_browser         =   exists(document.createElement);
        if ( httpobj_not_created_by_ie && is_modern_browser )
        {
             pinpad_oXMLHTTP = new XMLHttpRequest();
        }
  }







// ================================================================================
// LOGICAL FUNCTIONS  - use when not certain data-types are actual booleans
// ================================================================================


  function exists(x)          { return ( (typeof (x) != 'undefined') && (x != null) ); }

  function isfalse(aBoolean)  { return ( !(istrue(aBoolean)) ); }

  function istrue(aBoolean)
  {
      var emsg = 'TypeError: Non-Boolean used as a LOGICAL Boolean type!';
      switch (true)
      {
          case   ( !( exists(aBoolean) )          ) : return Boolean(false);             // break; //for
          case   ( typeof (aBoolean) == 'boolean' ) : return Boolean(aBoolean);          // break; //jslint
          case   ( aBoolean instanceof Boolean    ) : return istrue(aBoolean.valueOf()); // break;
          default                                   : throw  Error(emsg);                // break;
      }
  }
