
#include "nsCLABCMSEncoder.h"
#include "nsReadableUtils.h"
#include "nsComponentManagerUtils.h"
#include "nsCLABCMSMessage.h"
#include "nsMemory.h"

NS_IMPL_ISUPPORTS1(nsCLABCMSEncoder, nsICLABCMSEncoder)

/* void *arg, const char *buf, unsigned long len */
static void myCallback(void *arg,const char *buf,unsigned long len)
{
  nsCLABCMSEncoder * enc = (nsCLABCMSEncoder *) arg;
  enc->Eat(buf,len);
}
nsCLABCMSEncoder::nsCLABCMSEncoder()
{
  NS_INIT_ISUPPORTS();
  /* member initializers and constructor code */
  enc = do_CreateInstance(NS_CMSENCODER_CONTRACTID);
  output = nsnull;
}

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

/* void start (in nsICLABCMSMessage aMsg, in nsIOutputStream output); */
NS_IMETHODIMP nsCLABCMSEncoder::Start(nsICLABCMSMessage *aMsg, nsIOutputStream *output)
{
  nsCLABCMSMessage *clabMsg = NS_STATIC_CAST(nsCLABCMSMessage*, aMsg);
  this->output = output;

  eating_ns_error = NS_OK;
  eating_error = 0;

  return enc->Start(clabMsg->getCMSMessage(),myCallback,(void *)this);
}

/* void update (in string aBuf, in long aLen); */
NS_IMETHODIMP nsCLABCMSEncoder::Update(const char *aBuf, PRInt32 aLen)
{
  return enc->Update(aBuf,aLen);
}

/* void updateIstream (in nsIInputStream input); */
NS_IMETHODIMP nsCLABCMSEncoder::UpdateIstream(nsIInputStream *input)
{
    return NS_ERROR_NOT_IMPLEMENTED;
}

/* void finish (); */
NS_IMETHODIMP nsCLABCMSEncoder::Finish()
{
  nsresult rv;
  rv = enc->Finish();

  if (eating_error)
    return eating_ns_error;

  return rv;
}

/* void encode (in nsICLABCMSMessage aMsg, in nsIOutputStream output, in nsIInputStream input); */
NS_IMETHODIMP nsCLABCMSEncoder::Encode(nsICLABCMSMessage *aMsg, nsIOutputStream *output, nsIInputStream *input)
{
  nsresult rv;

  rv = Start(aMsg,output);
  if (NS_FAILED(rv)){
    return rv;
  }
  if (input != nsnull){
    rv = UpdateIstream(input);
    if (NS_FAILED(rv)){
      return rv;
    }
  }
  return Finish();
}

void nsCLABCMSEncoder::Eat(const char *buf,unsigned long len)
{
  nsresult rv;
  PRUint32 written;

  if (eating_error)
    return;

  if (!output){
    eating_error = 1;
    eating_ns_error = NS_ERROR_NULL_POINTER;
    return;
  }
    
  rv = output->Write((char *)buf,(PRUint32)len,&written);

  if (NS_FAILED(rv)){
    eating_ns_error = rv;
    eating_error = 1;
  }
  if (len != written){
    eating_error = rv;
    eating_ns_error =  NS_ERROR_FAILURE;//NS_ERROR_CANNOT_CONVERT_DATA;
  }
}
