NS_IMETHODIMP nsAbMDBDirectory::OnCardEntryChange
(uint32_t aAbCode, nsIAbCard *aCard, nsIAbDirectory *aParent)
{
  // Don't notify AbManager unless we have the parent
  if (!aParent)
    return NS_OK;

  NS_ENSURE_ARG_POINTER(aCard);
  nsCOMPtr<nsISupports> cardSupports(do_QueryInterface(aCard));
  nsresult rv;

  // Notify when
  // - any operation is done to a card belonging to this
  //        => if <this> is <aParent>, or
  // - a card belonging to a directory which is parent of this is deleted
  //        => if aAbCode is AB_NotifyDeleted && <this> is child of <aParent>, or
  // - a card belonging to a directory which is child of this is added/modified
  //        => if aAbCode is !AB_NotifyDeleted && <this> is parent of <aParent>

  if (aParent != this)
  {
    bool isChild = false;
    if (aAbCode != AB_NotifyDeleted)
      isChild = ContainsDirectory(this, aParent);
    else
      isChild = ContainsDirectory(aParent, this);

    if (!isChild)
      return NS_OK;
  }

  switch (aAbCode) {
  case AB_NotifyInserted:
    rv = NotifyItemAdded(cardSupports);
    break;
  case AB_NotifyDeleted:
    rv = NotifyItemDeleted(cardSupports);
    break;
  case AB_NotifyPropertyChanged:
    rv = NotifyItemChanged(cardSupports);
    break;
  default:
    rv = NS_ERROR_UNEXPECTED;
    break;
  }
    
  NS_ENSURE_SUCCESS(rv, rv);
  return rv;
}
NS_IMETHODIMP nsAbMDBDirectory::DeleteDirectory(nsIAbDirectory *directory)
{
  NS_ENSURE_ARG_POINTER(directory);

  nsCOMPtr<nsIAddrDatabase> database;
  nsresult rv = GetDatabase(getter_AddRefs(database));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = database->DeleteMailList(directory, PR_TRUE);

  if (NS_SUCCEEDED(rv))
    database->Commit(nsAddrDBCommitType::kLargeCommit);

  PRUint32 dirIndex;
  if (m_AddressList && NS_SUCCEEDED(m_AddressList->IndexOf(0, directory, &dirIndex)))
    m_AddressList->RemoveElementAt(dirIndex);
  rv = mSubDirectories.RemoveObject(directory);

  NotifyItemDeleted(directory);
  return rv;
}
NS_IMETHODIMP nsAbMDBDirectory::DeleteCards(nsIArray *aCards)
{
  NS_ENSURE_ARG_POINTER(aCards);
  nsresult rv = NS_OK;

  if (mIsQueryURI) {
    // if this is a query, delete the cards from the directory (without the query)
    // before we do the delete, make this directory (which represents the search)
    // a listener on the database, so that it will get notified when the cards are deleted
    // after delete, remove this query as a listener.
    nsCOMPtr<nsIAddrDatabase> database;
    rv = GetDatabase(getter_AddRefs(database));
    NS_ENSURE_SUCCESS(rv,rv);

    rv = database->AddListener(this);
    NS_ENSURE_SUCCESS(rv, rv);

    nsCOMPtr<nsIAbManager> abManager =
        do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
    NS_ENSURE_SUCCESS(rv, rv);

    nsCOMPtr<nsIAbDirectory> directory;
    rv = abManager->GetDirectory(mURINoQuery, getter_AddRefs(directory));
    NS_ENSURE_SUCCESS(rv, rv);

    rv = directory->DeleteCards(aCards);
    NS_ENSURE_SUCCESS(rv, rv);

    rv = database->RemoveListener(this);
    NS_ENSURE_SUCCESS(rv, rv);
    return rv;
  }

  if (!mDatabase)
    rv = GetAbDatabase();

  if (NS_SUCCEEDED(rv) && mDatabase)
  {
    uint32_t cardCount;
    uint32_t i;
    rv = aCards->GetLength(&cardCount);
    NS_ENSURE_SUCCESS(rv, rv);
    for (i = 0; i < cardCount; i++)
    {
      nsCOMPtr<nsIAbCard> card(do_QueryElementAt(aCards, i, &rv));
      NS_ENSURE_SUCCESS(rv, rv);

      if (card)
      {
        uint32_t rowID;
        rv = card->GetPropertyAsUint32("DbRowID", &rowID);
        NS_ENSURE_SUCCESS(rv, rv);

        if (m_IsMailList)
        {
          mDatabase->DeleteCardFromMailList(this, card, true);

          uint32_t cardTotal = 0;
          int32_t i;
          if (m_AddressList)
            rv = m_AddressList->GetLength(&cardTotal);
          for (i = cardTotal - 1; i >= 0; i--)
          {            
            nsCOMPtr<nsIAbCard> arrayCard(do_QueryElementAt(m_AddressList, i, &rv));
            if (arrayCard)
            {
              // No card can have a row ID of 0
              uint32_t arrayRowID = 0;
              arrayCard->GetPropertyAsUint32("DbRowID", &arrayRowID);
              if (rowID == arrayRowID)
                m_AddressList->RemoveElementAt(i);
            }
          }
        }
        else
        {
          mDatabase->DeleteCard(card, true, this);
          bool bIsMailList = false;
          card->GetIsMailList(&bIsMailList);
          if (bIsMailList)
          {
            //to do, get mailing list dir side uri and notify nsIAbManager to remove it
            nsAutoCString listUri(mURI);
            listUri.AppendLiteral("/MailList");
            listUri.AppendInt(rowID);
            if (!listUri.IsEmpty())
            {
              nsresult rv = NS_OK;

              nsCOMPtr<nsIAbManager> abManager =
                  do_GetService(NS_ABMANAGER_CONTRACTID, &rv);
              NS_ENSURE_SUCCESS(rv, rv);

              nsCOMPtr<nsIAbDirectory> listDir;
              rv = abManager->GetDirectory(listUri, getter_AddRefs(listDir));
              NS_ENSURE_SUCCESS(rv, rv);

              uint32_t dirIndex;
              if (m_AddressList && NS_SUCCEEDED(m_AddressList->IndexOf(0, listDir, &dirIndex)))
                m_AddressList->RemoveElementAt(dirIndex);

              mSubDirectories.RemoveObject(listDir);

              if (listDir)
                NotifyItemDeleted(listDir);
            }
          }
          else
          { 
            rv = RemoveCardFromAddressList(card);
            NS_ENSURE_SUCCESS(rv,rv);
          }
        }
      }
    }
    mDatabase->Commit(nsAddrDBCommitType::kLargeCommit);
  }
  return rv;
}
NS_IMETHODIMP nsAbMDBDirectory::DeleteCards(nsIArray *aCards)
{
  nsresult rv = NS_OK;

  if (mIsQueryURI) {
    // if this is a query, delete the cards from the directory (without the query)
    // before we do the delete, make this directory (which represents the search)
    // a listener on the database, so that it will get notified when the cards are deleted
    // after delete, remove this query as a listener.
    nsCOMPtr<nsIAddrDatabase> database;
    rv = GetDatabase(getter_AddRefs(database));
    NS_ENSURE_SUCCESS(rv,rv);

    rv = database->AddListener(this);
    NS_ENSURE_SUCCESS(rv, rv);

    nsCOMPtr<nsIRDFResource> resource;
    rv = gRDFService->GetResource(mURINoQuery, getter_AddRefs(resource));
    NS_ENSURE_SUCCESS(rv, rv);
    
    nsCOMPtr<nsIAbDirectory> directory = do_QueryInterface(resource, &rv);
    NS_ENSURE_SUCCESS(rv, rv);

    rv = directory->DeleteCards(aCards);
    NS_ENSURE_SUCCESS(rv, rv);

    rv = database->RemoveListener(this);
    NS_ENSURE_SUCCESS(rv, rv);
    return rv;
  }

  if (!mDatabase)
    rv = GetAbDatabase();

  if (NS_SUCCEEDED(rv) && mDatabase)
  {
    PRUint32 cardCount;
    PRUint32 i;
    rv = aCards->GetLength(&cardCount);
    NS_ENSURE_SUCCESS(rv, rv);
    for (i = 0; i < cardCount; i++)
    {
      nsCOMPtr<nsIAbCard> card(do_QueryElementAt(aCards, i, &rv));
      NS_ENSURE_SUCCESS(rv, rv);

      nsCOMPtr<nsIAbMDBCard> dbcard(do_QueryInterface(card, &rv));
      NS_ENSURE_SUCCESS(rv, rv);

      if (card)
      {
        if (m_IsMailList)
        {
          mDatabase->DeleteCardFromMailList(this, card, PR_TRUE);

          PRUint32 cardTotal = 0;
          PRInt32 i;
          if (m_AddressList)
            rv = m_AddressList->GetLength(&cardTotal);
          for (i = cardTotal - 1; i >= 0; i--)
          {            
            nsCOMPtr<nsIAbMDBCard> dbarrayCard(do_QueryElementAt(m_AddressList, i, &rv));
            if (dbarrayCard)
            {
              PRUint32 tableID, rowID, cardTableID, cardRowID; 
              dbarrayCard->GetDbTableID(&tableID);
              dbarrayCard->GetDbRowID(&rowID);
              dbcard->GetDbTableID(&cardTableID);
              dbcard->GetDbRowID(&cardRowID);
              if (tableID == cardTableID && rowID == cardRowID)
                m_AddressList->RemoveElementAt(i);
            }
          }
        }
        else
        {
          mDatabase->DeleteCard(card, PR_TRUE, this);
          PRBool bIsMailList = PR_FALSE;
          card->GetIsMailList(&bIsMailList);
          if (bIsMailList)
          {
            //to do, get mailing list dir side uri and notify rdf to remove it
            PRUint32 rowID;
            dbcard->GetDbRowID(&rowID);
            nsCAutoString listUri(mURI);
            listUri.AppendLiteral("/MailList");
            listUri.AppendInt(rowID);
            if (!listUri.IsEmpty())
            {
              nsresult rv = NS_OK;
              nsCOMPtr<nsIRDFService> rdfService = 
                       do_GetService("@mozilla.org/rdf/rdf-service;1", &rv);

              if (NS_FAILED(rv))
                return rv;

              nsCOMPtr<nsIRDFResource> listResource;
              rv = rdfService->GetResource(listUri,
                                           getter_AddRefs(listResource));
              nsCOMPtr<nsIAbDirectory> listDir = do_QueryInterface(listResource, &rv);
              if (NS_FAILED(rv))
                return rv;

              PRUint32 dirIndex;
              if (m_AddressList && NS_SUCCEEDED(m_AddressList->IndexOf(0, listDir, &dirIndex)))
                m_AddressList->RemoveElementAt(dirIndex);

              mSubDirectories.RemoveObject(listDir);

              if (listDir)
                NotifyItemDeleted(listDir);
            }
          }
          else
          { 
            rv = RemoveCardFromAddressList(card);
            NS_ENSURE_SUCCESS(rv,rv);
          }
        }
      }
    }
    mDatabase->Commit(nsAddrDBCommitType::kLargeCommit);
  }
  return rv;
}