#include "nsCLABHash.h"
#include "nsCOMPtr.h"

#include "nsComponentManagerUtils.h"
#include "nsMemory.h"

//#include "nspr.h"
//#include "plstr.h"


NS_IMPL_ISUPPORTS1(nsCLABHash, nsICLABHash)

nsCLABHash::nsCLABHash()
{
  NS_INIT_ISUPPORTS();
  /* member initializers and constructor code */
  ahash = do_CreateInstance(NS_HASH_CONTRACTID);
  hash_type = HASH_AlgNULL;
}

nsCLABHash::~nsCLABHash()
{
  /* destructor code */
}

/* unsigned long resultLen (in short aAlg); */
NS_IMETHODIMP nsCLABHash::ResultLen(PRInt16 aAlg, PRUint32 *_retval)
{
  //    return NS_ERROR_NOT_IMPLEMENTED;
  return ahash->ResultLen(aAlg,_retval);
}

/* void create (in short aAlg); */
NS_IMETHODIMP nsCLABHash::Create(PRInt16 aAlg)
{
  //    return NS_ERROR_NOT_IMPLEMENTED;
  
  switch(aAlg){
  case HASH_AlgMD2:
    hash_type = nsIHash::HASH_AlgMD2;
    break;
  case HASH_AlgMD5:
    hash_type = nsIHash::HASH_AlgMD5;
    break;
  case HASH_AlgSHA1:;
    hash_type = nsIHash::HASH_AlgSHA1;
    break;
  }

  return ahash->Create(hash_type);
}

/* void begin (); */
NS_IMETHODIMP nsCLABHash::Begin()
{
  //    return NS_ERROR_NOT_IMPLEMENTED;
  return ahash->Begin();
}

/* void update (in string data); */
NS_IMETHODIMP nsCLABHash::Update(const char *data, PRUint32 aLength)
{
  //    return NS_ERROR_NOT_IMPLEMENTED;
  PRUint32 sec_item_len;
  unsigned char * sec_item_data = nsnull;
  int status;
  nsresult rv = NS_OK;

  sec_item_len  = aLength; //PL_strlen(data);
  sec_item_data = (unsigned char *) nsMemory::Clone(data,sec_item_len);//PR_MALLOC(sec_item_len);
  if (!sec_item_data)   {
    status = NS_ERROR_OUT_OF_MEMORY;
    goto FAIL;
  }
  //PR_SetError(0,0);

  // COPY MEMORY
  //memcpy(sec_item_data,data,sec_item_len);
  
  //status = PR_GetError();
  //if (status < 0) {
  //rv = NS_ERROR_FAILURE;
  //goto FAIL;
  //}

  //PR_SetError(0,0);
  rv = ahash->Update(sec_item_data,sec_item_len);

FAIL:
  //PR_FREEIF(sec_item_data);
  if (sec_item_data) nsMemory::Free(sec_item_data);

  return rv;
}

/* void end (out unsigned long len, [size_is (len), retval] out string data); */
NS_IMETHODIMP nsCLABHash::End(PRUint32 *len, char **data)
{
  //    return NS_ERROR_NOT_IMPLEMENTED;
    nsresult rv = NS_OK;
    char *buffer = nsnull;
    PRUint32 sec_item_len,out_len;
    

    ahash->ResultLen(hash_type, &sec_item_len);

    buffer = (char*)nsMemory::Alloc(sec_item_len);
    if (!buffer) return NS_ERROR_OUT_OF_MEMORY;

    rv = ahash->End((unsigned char *)buffer,&out_len,sec_item_len);

    //memset(buffer,0,sec_item_len);

    *data = buffer;
    *len = sec_item_len;

    return rv;
}


