var Biff = false;

function LogX(str){
 var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].
                                getService(Components.interfaces.nsIWindowMediator);
 var logWindow = windowManager.getMostRecentWindow("Log:Window");
 var text = logWindow.document.getElementById("logtext");
 text.value = text.value + str;
}

addEventListener("load",OnLoadUpdate,true);

function OnLoadUpdate()
{
  var folder = GetSelectedMsgFolder();
  if(folder!=null){
    if(BASEnabled()){
      var user = folder.server.username;
      UpdateCreditsAsync = UpdateCredits(user);
      UpdateCreditsAsync.next();
    }
  }
}

var Headers = null;
function InitHeaders(folder){
  var newHeaders = Components.classes["@mozilla.org/supports-array;1"].createInstance( Components.interfaces.nsISupportsArray );
  var mDB = folder.getMsgDatabase( null );
  var enum = mDB.EnumerateMessages();
  while ( enum.hasMoreElements() ) {
    var header = enum.getNext().QueryInterface(Components.interfaces.nsIMsgDBHdr);
    newHeaders.AppendElement(header);
  }
  return newHeaders;
}

AddToSessionOrig = AddToSession;
AddToSession = function(){
  res = AddToSessionOrig();
  try{
    var mailSession = Components.classes[mailSessionContractID]
                                .getService(Components.interfaces.nsIMsgMailSession);
    var nsIFolderListener = Components.interfaces.nsIFolderListener;
    var notifyFlags = nsIFolderListener.intPropertyChanged | nsIFolderListener.event;
    mailSession.AddFolderListener(myFolderListener, notifyFlags);
    Headers = null;
  }
  catch(ex){
  }
  return res;
}

function SetFolders(RootFolder){
  // create folders if they don't exist
  if (!RootFolder.containsChildNamed("BAS Inbox"))
    NewFolder("BAS Inbox", RootFolder.URI);
  if (!RootFolder.containsChildNamed("BAS Spam"))
    NewFolder("BAS Spam", RootFolder.URI);
}

function Inbox(Folder){
  return Folder.rootFolder.getChildNamed("Inbox").QueryInterface(Components.interfaces.nsIMsgFolder);
}

function InboxFolder(Folder){
  return Folder.rootFolder.getChildNamed("BAS Inbox").QueryInterface(Components.interfaces.nsIMsgFolder);
}

function SpamFolder(Folder){
  return Folder.rootFolder.getChildNamed("BAS Spam").QueryInterface(Components.interfaces.nsIMsgFolder);
}

function AlertInboxFolder(Folder){
  //LogX("once.\n");
  InboxFolder(Folder).setNumNewMessages(1);
  InboxFolder(Folder).biffState = 0;
}

function MoveNewMessage(Header, toFolder){
  //LogX("Moving...\n");
  var fromFolder = Header.folder;
  var aMsgHdrs = Components.classes["@mozilla.org/supports-array;1"].
                            createInstance(Components.interfaces.nsISupportsArray);
  aMsgHdrs.AppendElement(Header);
  var copyService = Components.classes["@mozilla.org/messenger/messagecopyservice;1"].
                               getService(Components.interfaces.nsIMsgCopyService);
  var mailMoverListener =
  {
    OnStopCopy: function( status ){ 
      SynchronizeAsync.next();
    },
    GetMessageId    : function(messageId) { },
    OnProgress      : function(progress, progressMax) { },
    OnStartCopy     : function() { 
    },
    SetMessageKey   : function(key) { },
  };  

  var SynchronizeAsync;
  function Synchronize(){
    copyService.CopyMessages(fromFolder, aMsgHdrs, toFolder, true, mailMoverListener, msgWindow, false);
    yield;
    //LogX("Move completed.\n");
    Biff = true;
  }
  var SynchronizeAsync = Synchronize();
  SynchronizeAsync.next();
}

function MoveMessage(Header, toFolder){
  //LogX("Moving...\n");
  var fromFolder = Header.folder;
  var aMsgHdrs = Components.classes["@mozilla.org/supports-array;1"].
                            createInstance(Components.interfaces.nsISupportsArray);
  aMsgHdrs.AppendElement(Header);
  toFolder.copyMessages(fromFolder, aMsgHdrs, true, msgWindow, null, true, false);
}

function MarkMessageRead(Header){
  var aMsgHdrs = Components.classes["@mozilla.org/supports-array;1"].
                            createInstance(Components.interfaces.nsISupportsArray);
  aMsgHdrs.AppendElement(Header);
  Header.folder.markMessagesRead(aMsgHdrs, true);
}

function SendBodyStamp(Header){
  //LogX("Receiving sent body...\n");
  var SentBody = "";
  var uri = Header.folder.getUriForMsg(Header);
  var server = Header.folder.server;
  var messageService = messenger.messageServiceFromURI(uri);

  var ProcessSentMessageAsync;
  function ProcessSentMessage(){
    SendStampAsync = SendStamp(server.username, Header.recipients, MD5(CleanBody(SentBody)));
    SendStampAsync.next();
  }

  var SendDataListener = {
    QueryInterface: function(aIID) {
      if (aIID.equals(Components.interfaces.nsISupports) || aIID.equals(Components.interfaces.nsIStreamListener))
        return this;
      throw Components.results.NS_NOINTERFACE;
    },
    onStartRequest: function() {
      SentBody = "";
    },
    onStopRequest: function() {
      //LogX("Got sent body!\n");
      ProcessSentMessageAsync = ProcessSentMessage();
      ProcessSentMessageAsync.next();
    },
    onDataAvailable:function(req, context, inputStream, offset, count) {
      var sStream = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance().QueryInterface(Components.interfaces.nsIScriptableInputStream);
      sStream.init(inputStream);
      sStream.available();
      while (sStream.available()) {
        SentBody += sStream.read(count);
      }
    } 
  };
  messageService.streamMessage(uri, SendDataListener, {}, null, true, null);
}

function CheckBodyStamp(Header){
  //LogX("Receiving inbox body...\n");
  var ReceivedBody = "";
  var uri = Header.folder.getUriForMsg(Header);
  var server = Header.folder.server;
  var messageService = messenger.messageServiceFromURI(uri);

  var ProcessReceivedMessageAsync;
  function ProcessReceivedMessage(){
    //LogX("Processing...\n");
    BASObjectLog("C:\\day.txt", Header);
    CheckStampAsync = CheckStamp(ProcessReceivedMessageAsync, Header.author, server.username, MD5(CleanBody(ReceivedBody)));
    CheckStampAsync.next();
    var res = yield;
    if (res == false){
      MarkMessageRead(Header);
      MoveMessage(Header, SpamFolder(Header.folder));
    } else {
      MoveNewMessage(Header, InboxFolder(Header.folder));
    }
  }

  var ReceiveDataListener = {
    QueryInterface: function(aIID) {
      if (aIID.equals(Components.interfaces.nsISupports) || aIID.equals(Components.interfaces.nsIStreamListener))
        return this;
      throw Components.results.NS_NOINTERFACE;
    },
    onStartRequest: function() {
      ReceivedBody = "";
    },
    onStopRequest: function() {
      //LogX("Received Body!\n");
      ProcessReceivedMessageAsync = ProcessReceivedMessage();
      ProcessReceivedMessageAsync.next();
    },
    onDataAvailable:function(req, context, inputStream, offset, count) {
      var sStream = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance().QueryInterface(Components.interfaces.nsIScriptableInputStream);
      sStream.init(inputStream);
      sStream.available();
      while (sStream.available()) {
        ReceivedBody += sStream.read(count);
      }
    }
  };
  messageService.streamMessage(uri, ReceiveDataListener, {}, null, true, null);
}

function IsMessageSent(){
  var mailWindow = GetWindow("mail:3pane");
  var sentMessage = mailWindow.document.getElementById("sentmessage").value;
  return (sentMessage=="true");
}

function GetSentMessageSubject(){
  var mailWindow = GetWindow("mail:3pane");
  var sentMessageSubject = mailWindow.document.getElementById("sentmessagesubject").value;
  return sentMessageSubject;
}

function ClearSentData(){
  var mailWindow = GetWindow("mail:3pane");
  mailWindow.document.getElementById("sentmessage").value = "false";
  mailWindow.document.getElementById("sentmessagesubject").value = "";
}

var myFolderListener = {
    OnItemAdded: function(parentItem, item) { 
      //LogX("OnItemAdded\n");
    },

    OnItemRemoved: function(parentItem, item) { 
      //LogX("OnItemRemoved\n");
    },

    OnItemPropertyChanged: function(item, property, oldValue, newValue) { 
      //LogX("OnItemPropertyChanged\n");
    },

    OnItemIntPropertyChanged: function(item, property, oldValue, newValue) {
      //LogX("OnItemIntPropertyChanged\n");
      if(!BASEnabled())
        return;
      if (property == "BiffState"){
        var folder = item.QueryInterface(Components.interfaces.nsIMsgFolder);
        //LogX(folder.name + "[" + property + "] : " + oldValue + " -> " + newValue + "\n");
      }
      try{
        var folder = item.QueryInterface(Components.interfaces.nsIMsgFolder);
        if (property == "TotalMessages"){
          if ((folder.flags & 0x200) == 0x200){
            folder.updateFolder(null);
            if (IsMessageSent()){
              var mDB = folder.getMsgDatabase(null);
              var enum = mDB.EnumerateMessages();
              while (enum.hasMoreElements()) {
                var header = enum.getNext().QueryInterface(Components.interfaces.nsIMsgDBHdr);
                if (Headers.GetIndexOf(header) == -1){ // new message in sent folder
                  //LogX("New mail : " + header.subject + "\n");
                  if (GetSentMessageSubject() == header.subject){
                    //LogX("Header matched.\n");
                    SendBodyStamp(header);  // listener reads body data and acknowledges server
                    ClearSentData();
                  }
                }
              }
            }
            Headers = InitHeaders(folder);
          }
        }
        if (property == "TotalUnreadMessages"){
          if ((folder.flags & 0x1000) == 0x1000) {
	    SetFolders(folder.rootFolder);	
            var mDB = folder.getMsgDatabase(null);
            var enum = mDB.EnumerateMessages();
            while (enum.hasMoreElements()) {
              var header = enum.getNext().QueryInterface(Components.interfaces.nsIMsgDBHdr);
              if (!header.isRead){
                //LogX("New Inbox Msg!\n");
                InboxFolder(folder).biffState = 1;
                folder.biffState = 1;
                CheckBodyStamp(header); // async operation
              }
            }
          }
        }
      }
      catch(ex){
        alert(ex);
      }
    },

    OnItemBoolPropertyChanged: function(item, property, oldValue, newValue) { 
      //LogX("OnItemBoolPropertyChanged\n");
    },

    OnItemUnicharPropertyChanged: function(item, property, oldValue, newValue) { 
      //LogX("OnItemUnicharPropertyChanged\n");
    },

    OnItemPropertyFlagChanged: function(item, property, oldFlag, newFlag) { 
      //LogX("OnItemPropertyFlagChanged\n");
    },

    OnItemEvent: function(folder, event) { 
      //LogX("OnItemEvent : " + event + "\n");
      if(!BASEnabled())
        return;
      if (event == "FolderLoaded"){
        if (Biff) {
	  AlertInboxFolder(folder);
          Biff = false;
        }
        if(BASEnabled()){
          var user = folder.server.username;
          UpdateCreditsAsync = UpdateCredits(user);
          UpdateCreditsAsync.next();
        }
      }
      if (Headers == null){
        try{
          folder = folder.QueryInterface(Components.interfaces.nsIMsgFolder);
          folder.updateFolder(null);
          var outNumFolders = new Object();
          var sendFolder = folder.rootFolder.getFoldersWithFlag(0x200, 1, outNumFolders);
          Headers = InitHeaders(sendFolder);
        }
        catch(ex){
        }
      }
      //LogX("Count : " + Headers.Count() + "\n");
    }
}
