//////////////////////////////////////////
//           ajaximrpg 5.00             //
//       AJAX Instant Messenger         //
//  Copyright (c) 2006-2008, 2010-2012  //
//      Do not remove this notice       //
//////////////////////////////////////////

/**
 * Handles session and most requests to the server
 */
var System = {
   /**
    * Login the user. If it fails, show an error dialog box.
    * 
    * @arguments u - username (if undefined, get from Login dialog) p - password
    *            (if undefined, get from Login dialog)
    * 
    * @author Joshua Gross
    * @update Benjamin Hutchins
    * @update Daniel Howard
    */
   login: function(u, p) {
      var username = (u? u: $('username').value);
      var password = hex_md5(p? p: $('password').value);
   
      var xhConn = new XHConn();
      xhConn.connect(pingTo, "POST", "call=login&username="+username+"&password="+password, function(xh) {
         installCheckComplete = true;
         if (xh.outputText.indexOf('"') == -1) {
            var errmsg = '';
            if (xh.outputText == 'invalid') {
               errmsg = Languages.get('incorrectInfo');
            } else if (xh.outputText == 'banned') {
               errmsg = Languages.get('userBanned');
            }
            if (!$('login')) {
               // maybe invalid database that checkinstall didn't catch
               Dialogs.login();
            }
            $('login_error_msg').innerHTML = errmsg;
            $('login_error_msg').show();
            new Effect.Shake('login');
         } else {
            var response = xh.outputText.evalJSON(true);
            if ($('login')) {
               Windows.close('login');
            }
            var alreadyLoggedIn = (user != '');
            loggedIn = true;
            user = response.username; // server returns unique username for anonymous logins
            pass = hex_md5(password);
            System.switchUser(response);
            if (!alreadyLoggedIn) {
               Event.observe(document, 'focus', function() {
                  blinkerOn(false);
               });
               Event.observe(window, 'focus', function() {
                  blinkerOn(false);
               });
               Event.observe(document, 'blur', function() {
                  blinkerOn(true);
               });
               Event.observe(window, 'blur', function() {
                  blinkerOn(true);
               });
      
               Event.observe(document, 'keypress', function(event) {
                  event = event || window.event;
                  if (Windows.focusedWindow.getId().indexOf('_im') != -1 && Chatroom.sendBoxWithFocus == null) {
                     var sB = $(Windows.focusedWindow.getId() + '_sendBox');
                     sB.focus();
                     sB.value += String.fromCharCode(event.charCode);
                  }
               });
      
               if (predefRooms.length >= 1) {
                  // ensure that room list panel creation is done
                  setIntervalCheck(function() {
                     if ($('join_room_ul')) {
                        Chatroom.join(predefRooms[0], 'anonymous');
                        return false;
                     }
                  }, 200, 20);
               }
            }
         }
      });
   },
   
   /**
    * Switch to a different account.
    * 
    * @arguments u - username (if undefined, get from Login dialog) p - password
    *            (if undefined, get from Login dialog)
    * 
    * @author Daniel Howard
    */
   switchUser: function(response) {
      defaultTitle = document.title;
      document.title = document.title + ': ' + user;
      $('languageList').hide();
      if (pingTimer == null) {
         pingTimer = setInterval('System.ping()', pingFrequency);
      }
      if (typeof (Roomlist) != 'undefined') {
         Roomlist.create();
      }
      if (typeof (Roomlist) != 'undefined') {
         Roomlist.build(response);
      }
      if (response.admin == 1) {
         var s = document.createElement('script');
         s.src = 'js/admin.js?' + (new Date()).getTime();
         s.type = 'text/javascript';
         document.getElementsByTagName('head').item(0).appendChild(s);
         $('blBottomToolbar').innerHTML += '<a id="admin-button" href="#" onclick="AdminWindows.userSearch();return false;" title="Admin"><img src="themes/' + theme + '/window/admin.png" alt="Admin" style="border:0;" /></a>';
         $('admin-button').setStyle( { 'position': 'absolute', 'left': '0', 'top': '0' });
      }
      Status.lastIM = new Date().getTime();
      System.ping();
   },
   
   /**
    * Log out the user.
    * 
    * @author Joshua Gross
    */
   logout: function() {
      if ((user == '') || (pass == '')) {
         return;
      }
      var xmlhttp = false;
      /*@cc_on @*/ 
      /*@if (@_jscript_version >= 5) 
      try { 
         xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); 
      } catch (e) { 
         try { 
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); 
         } catch (E) { 
            xmlhttp = false; 
         } 
      } 
      @end @*/
      if (!xmlhttp && (typeof XMLHttpRequest != 'undefined')) {
         xmlhttp = new XMLHttpRequest();
      }
      xmlhttp.open('POST', pingTo, false);
      xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
      xmlhttp.send('call=logout&user=' + user);
      clearTimeout(pingTimer);
      pingTimer = null;
      defaultTitle = document.title = document.title.replace(': ' + user, '');
      user = '';
      pass = '';
      loggedIn = false;
      Chatroom.position = 0;
      if (typeof (Status) != 'undefined') {
         Status.state = Status.online;
         Status.awayMessage = '';
      }
      if (typeof (Roomlist) != 'undefined') {
         Roomlist.destroy();
      }
      for ( var name in IM.windows) {
         if (typeof (IM.windows[name].getId) != 'undefined' && typeof ($(IM.windows[name].getId())) != 'undefined') {
            try {
               if (IM.windows[name].detached) {
                  IM.windows[name].popup.close();
               } else {
                  IM.windows[name].destroy();
               }
            } catch (e) {
            }
         }
      }
   
      for ( var name in Chatroom.windows) {
         if (typeof (Chatroom.windows[name].getId) != 'undefined' && typeof ($(Chatroom.windows[name].getId())) != 'undefined') {
            try {
               Chatroom.windows[name].destroy();
            } catch (e) {
            }
         }
      }
      if ($('admin-userSearch')) {
         Windows.getWindow('admin-userSearch').destroy();
      }
   
      Dialog.alert('<span class="dialog_long_label">' + Languages.get('signedOff') + '</span>', {
      windowParameters: {
      className: 'alert',
      width: alertWidth,
      height: 85
      },
      okLabel: Languages.get('reconnect'),
      ok: function(win) {
         try {
            window.location.reload();
         } catch (e) {
         }
      }
      });
   },
   
   /**
    * Ping the server for new events and messages. The heart of this script.
    * 
    * @author Joshua Gross
    */
   ping: function() {
      // set user to away after a period of inactivity
      if (idleTime > 0) {
         var timeout = new Date().getTime() - (idleTime * 60 * 1000);
         if ((typeof (Status) != 'undefined') && (Status.lastIM < timeout) && (Status.state == Status.online)) {
            Status.set(Status.away, Languages.get('away'));
            Status.wasSetAutoAway = true;
         }
      }
   
      // call 'ping' action
      var status = (typeof (Status) != 'undefined')? Status.state: 0;
      var xhConn = new XHConn();
      xhConn.connect(pingTo, "POST", "call=ping&status=" + status, function(xh) {
         if (((typeof xh.status != 'undefined') && (xh.status != 200)) || (xh.outputText.substring(0, 13) == 'not_logged_in')) {
            System.logout();
            return;
         }
         if (trim(xh.outputText).length == 0) {
            return;
         }
         // decode the events which in "call=ping" response
         var response = xh.outputText.evalJSON(true);
         var messageCount = 0;
         var eventCount = (typeof(response.events) !== 'undefined')? response.events.length: 0;
         for (var i=0; i < eventCount; i++) {
            switch (response.events[i].type) {
               case 'room':
                  if (response.events[i].action == 'add') {
                     Roomlist.addRoom(response.events[i].room);
                     var in_im = (response.events[i].room.substring(0, 3) == 'im_');
                     if (in_im && (response.events[i].from != user)) {
                        Chatroom.joinIM(response.events[i].from);
                     }
                  } else if (response.events[i].action == 'delete') {
                     var deleteRoom = true;
                     for (var d=0; d < predefRooms.length; d++) {
                        if (predefRooms[d] == response.events[i].room) {
                           deleteRoom = false;
                        }
                     }
                     if (deleteRoom) {
                        Roomlist.deleteRoom(response.events[i].room);
                     }
                  }
                  break;
               case 'chat':
                  var in_im = (response.events[i].room.substring(0, 3) == 'im_');
                  var win = Chatroom.windows[response.events[i].room];
                  if ((win != null) && (typeof (win) != 'undefined')) {
                     var rcvdBox = $(win.getId() + "_rcvd");
                     if (response.events[i].action == 'join') {
                        if (!in_im && !$(response.events[i].from + '_' + response.events[i].room + '_chatUser')) {
                           win.addUser(response.events[i].from, response.events[i].from, Status.online);
                        }
                        rcvdBox.innerHTML += response.events[i].html;
                        scrollToBottom(win.getId() + "_rcvd");
                     } else if (response.events[i].action == 'left') {
                        if (response.events[i].room.split('_', 2)[0] != 'im') {
                           win.deleteUser(response.events[i].from);
                        }
                        rcvdBox.innerHTML += response.events[i].html;
                        scrollToBottom(win.getId() + "_rcvd");
                     }
                  }
                  break;
               case 'user':
                  if (response.events[i].action == 'change') {
                     for (var room in Chatroom.windows) {
                        if ((typeof(Chatroom.windows[room].getId) != 'undefined') && (typeof($(Chatroom.windows[room].getId())) != 'undefined')) {
                           Chatroom.windows[room].changeUser(response.events[i].oldlogin, response.events[i].newlogin);
                        }
                     }
                  } else if (response.events[i].action == 'alias') {
                     var win = Chatroom.windows[response.events[i].room];
                     var rcvdBox = $(win.getId() + "_rcvd");
                     win.changeAlias(response.events[i].from, response.events[i].alias);
                     rcvdBox.innerHTML += response.events[i].html;
                     scrollToBottom(win.getId() + "_rcvd");
                  }
                  break;
               case 'status':
                  if (typeof(Roomlist) != 'undefined') {
                     Roomlist.setUserStatus(response.events[i].from, response.events[i].status);
                  }
                  for (var room in Chatroom.windows) {
                     if ((typeof(Chatroom.windows[room].getId) != 'undefined') && (typeof($(Chatroom.windows[room].getId())) != 'undefined')) {
                        Chatroom.windows[room].setUserStatus(response.events[i].from, response.events[i].status);
                     }
                  }
                  break;
               case 'msg':
                  ++messageCount;

                  var from = response.events[i].from;
                  var room = response.events[i].room;

                  if ((typeof(Chatroom.windows[room].getId) != 'undefined') && (typeof($(Chatroom.windows[room].getId())) != 'undefined')) {
                     var winObj = Chatroom.windows[room];
                     var winId = winObj.getId();
                     var rcvdBox = (!winObj.detached? $(winId + "_rcvd"): winObj.popup.$(winId + "_rcvd"));

                     var html = response.events[i].html;

                     html = IM.emoteReplace(html, smilies);

                     //TODO convert links; do this on server
//                     html = html.replace(/(\s|\n|>|^)(\w+:\/\/[^<\s\n]+)/, '$1<a href="$2" target="_blank">$2</a>');

                     rcvdBox.innerHTML += html;
                     rcvdBox.scrollTop = rcvdBox.scrollHeight - rcvdBox.clientHeight + 6;

                     if (pulsateTitles && (Windows.getFocusedWindow().getId() != winId)) {
                        new Effect.Pulsate(winId + '_top');
                     }

                     if (titlebarBlinker && useBlinker) {
                        var blinkerText = html.replace(/\"/, '\"').replace(/<([^>]+)>/ig, '');
                        clearTimeout(blinkerTimer);
                        blinkerTimer = setTimeout("titlebarBlink('" + room + "', \"" + blinkerText + "\", 0)", blinkSpeed);
                     }
                     rcvdBox = null;
                  } else {
                     alert('System.ping: room "'+room+'" does not exist');
                  }
                  break;
               case 'share':
                  if (response.events[i].message.indexOf('/share ') == 0) {
                     IM.sendMessage(response.events[i].from, response.events[i].room, response.events[i].message);
                  }
                  break;
               case 'sync':
                  var plugins_a = makeArray(plugins);
                  for (var p=0; p < plugins_a.length; p++) {
                     if ((typeof plugins_a[p].handleSync) == 'function') {
                        plugins_a[p].handleSync(response.events[i]);
                     }
                  }
                  break;
            }
         }
   
         if (audioNotify && (messageCount > 0)) {
            soundManager.play('msg_in');
         }
      });
      xhConn = null;
   },
   
   /**
    * Rename the current account on the fly and switch to it. If it fails, show an
    * error dialog box.
    * 
    * @arguments u - username (if undefined, get from Login dialog) p - password
    *            (if undefined, get from Login dialog)
    * 
    * @author Daniel Howard
    */
   register: function() {
      var username = $('newusername').value;
      var password = $('newpassword').value;
      var confirm = $('newconfirm').value;
      var email = $('newemail').value;
   
      var xhConn = new XHConn();
      xhConn.connect(pingTo, "POST", "call=register&username="+username+"&password="+password+"&confirm="+confirm+"&email="+email, function(xh) {
         if (xh.outputText.indexOf('"') != -1) {
            Windows.getWindow('register').setCloseCallback(function () { return true; });
            Windows.close('register');
            var response = xh.outputText.evalJSON(true);
            loggedIn = true;
            user = response.username; // server returns unique username for anonymous logins
            pass = hex_md5(password);
            System.switchUser(response);
         } else {
            switch (xh.outputText) {
               case 'username_bad':
                  error = Languages.get('registerUsernameBad');
                  break;
               case 'username_taken':
                  error = Languages.get('registerUsernameTaken');
                  break;
               case 'password_bad_length':
                  error = Languages.get('registerPasswordShort');
                  break;
               case 'passwords_no_match':
                  error = Languages.get('registerPasswordsMatch');
                  break;
               case 'invalid_email':
                  error = Languages.get('registerInvalidEmail');
                  break;
               case 'email_already_used':
                  error = Languages.get('registerEmailTaken');
                  break;
               default:
                  error = Languages.get('registerFailed');
            }
            $('register_error_msg').innerHTML = error;
            $('register_error_msg').setStyle( { display: 'block' });
            new Effect.Shake('register');
         }
      });
   },
   
   /**
    * Change a user's password
    * 
    * @author Joshua Gross
    * @update Benjamin Hutchins
    */
   changePass: function() {
      var currentPw = $('currentpw').value, newPw = $('newpw').value, error = '';
   
      if (hex_md5(currentPw) == pass) {
         if (newPw == $('confirmpw').value) {
            var xhConn = new XHConn();
            xhConn.connect(pingTo, "POST", "call=pwdchange&username=" + user + "&password=" + hex_md5(currentPw) + "&newpwd=" + newPw, function(xh) {
               if (xh.outputText == 'pw_changed') {
                  Dialog.closeInfo();
                  Dialog.alert('<span class="dialog_long_label lang-changeSuccess">' + Languages.get('changeSuccess') + '</span><div style="clear:both"></div>', {
                  windowParameters: {
                  className: 'alert',
                  width: alertWidth,
                  height: 85
                  },
                  ok: function(win) {
                     Dialog.closeInfo();
                     Windows.close('changePass');
                  }
                  });
               } else if (xh.outputText == 'invalid_pw') {
                  error = Languages.get('currentPassInvalid');
                  $('currentpw').value = '';
               } else if (xh.outputText == 'password_bad_length') {
                  error = Languages.get('changePasswordShort');
                  $('newpw').value = '';
                  $('confirmpw').value = '';
               } else {
                  error = Languages.get('changeFailed');
               }
               if (error.length > 0) {
                  $('changepass_error_msg').innerHTML = error;
               }
            });
         } else {
            error = Languages.get('changeNoMatch');
         }
      } else {
         error = Languages.get('currentPassInvalid');
      }
      if (error.length > 0) {
         $('changepass_error_msg').innerHTML = error;
      }
   },
   
   /**
    * Reset a user's password to something new because they forgot it
    * 
    * @author Joshua Gross
    * @update Benjamin Hutchins
    */
   resetPass: function() {
      var xhConn = new XHConn();
      xhConn.connect(pingTo, "POST", "call=reset&email=" + encodeURIComponent($('resetto').value), function(xh) {
         var error = '';
         if (xh.outputText == 'pw_reset') {
            Dialog.alert('<span class="dialog_long_label lang-newPasswordEmailed langinsert-clear">' + Languages.get('newPasswordEmailed').replace('%1', $('resetto').value) + '</span><div style="clear:both"></div>', {
               windowParameters: { className: 'alert',  width: alertWidth  },
               ok: function(win) {
                  clearInputs();
                  Dialog.closeInfo();
                  Dialogs.login();
               }
            });
         } else if (xh.outputText == 'no_email_on_record') {
            error = Languages.get('noEmailOnRecord');
         } else {
            error = Languages.get('problemResetting');
         }
   
         if (error.length > 0) {
            $('forgotPass_error_msg').innerHTML = error;
            $('forgotPass_error_msg').setStyle( { display: 'block' });
            new Effect.Shake('forgotPass');
         }
      });
   },
   
   /**
    * Update a user's alias
    * 
    * @author Daniel Howard
    */
   changeAlias: function(room, alias) {
      var xhConn = new XHConn();
      xhConn.connect(pingTo, "POST", "call=changealias&room=" + room + "&alias=" + alias, function(xh) {
         if (xh.outputText == 'success') {
         } else {
            error = Languages.get('changeProfileFailed');
         }
      });
   },
   
   /**
    * Update a user's budddy profile
    * 
    * @author Benjamin Hutchins
    */
   changeProfile: function() {
      var profile = $('changeprofile_textarea').value, error = '';
      if (profile.replace(/\s/g, "") != "") {
         var xhConn = new XHConn();
         xhConn.connect(pingTo, "POST", "call=changeprofile&profile=" + encodeURIComponent(profile), function(xh) {
            if (xh.outputText == 'success') {
               Dialog.closeInfo();
               Dialog.alert('<span class="dialog_long_label lang-changeProfileSuccess">' + Languages.get('changeProfileSuccess') + '</span><div style="clear:both"></div>', {
               windowParameters: {
               className: 'alert',
               width: alertWidth,
               height: 85
               },
               ok: function(win) {
                  Dialog.closeInfo();
                  Windows.close('changeProfile');
               }
               });
            } else {
               error = Languages.get('changeProfileFailed');
            }
   
            if (error.length > 0) {
               $('changeprofile_error_msg').innerHTML = error;
            }
         });
      } else {
         error = Languages.get('changeProfileEmpty');
      }
      if (error.length > 0) {
         $('changeprofile_error_msg').innerHTML = error;
      }
   },
   
   /**
    * Update a users's buddy icon
    * 
    * @author Benjamin Hutchins
    */
   changeIcon: function() {
      // get the iframe as a variable
      var i = $('changeicon_iframe');
      if (i.contentDocument) {
         var d = i.contentDocument;
      } else if (i.contentWindow) {
         var d = i.contentWindow.document;
      } else {
         var d = window.frames['changeicon_iframe'].document;
      }
   
      // if the iframe was never processed, then return empty
      if (d.location.href == "about:blank") {
         return;
      }
   
      // handle returns from the server
      var error = '', response = d.body.innerHTML;
      if (response.indexOf('__output__') == 0) {
         response = response.substring('__output__'.length);
      }
      if (response == 'success') {
         Dialog.closeInfo();
         Dialog.alert('<span class="dialog_long_label lang-changeBuddyiconSuccess">' + Languages.get('changeBuddyiconSuccess') + '</span><div style="clear:both"></div>', {
         windowParameters: {
         className: 'alert',
         width: alertWidth,
         height: 85
         },
         ok: function(win) {
            Dialog.closeInfo();
            Windows.close('changeIcon');
         }
         });
      } else if (response == 'nofile') {
         error = Languages.get('changeIconSelectFile');
      } else if (response == 'size') {
         error = Languages.get('changeIconSize');
      } else if (response == 'bad_type') {
         error = Languages.get('changeIconBadType');
      } else if (response == 'bad_extension') {
         error = Languages.get('changeIconBadExtension');
      } else {
         error = Languages.get('changeIconFailed');
      }
   
      // if there was an error, show it
      if (error.length > 0) {
         $('changeicon_error_msg').innerHTML = error;
      }
   },
   
   /**
    * Simple 'onkeypress' event handler for text inputs to invoke func() on
    * Enter/Return key.
    * 
    * @author Benjamin Hutchins
    */
   keyHandler: function(event, func) {
      event = event || window.event;
      var asc = document.all? event.keyCode: event.which;
      if ((asc == 13) && (typeof func == 'function')) {
         func();
      }
      return asc != 13;
   }
};

