package de.tu_dresden.diplom.richter_mirko_mat2628335.witness.account;

import org.apache.log4j.Logger;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.account.IFAmount;

/**
 * 
 */
public class AccountTransferContext implements IFAccountTransferContext{

   private static final Logger logger = Logger.getLogger(AccountTransferContext.class);

   private IFAccount sourceAccount = null;
   private IFAccount targetAccount = null;

   private IFAmount transferValue = null;
   private IFVirtualDebit debit = null;
   private IFVirtualCredit credit = null;

   private boolean valid = true;

   public AccountTransferContext(IFAccount sourceAccount, IFAccount targetAccount, IFAmount transferValue) {
      this.sourceAccount = sourceAccount;
      this.targetAccount = targetAccount;
      this.transferValue = transferValue;
      checkTransferContext();
   }

   public void stopTransfer(){
      sourceAccount.removeVirtualDebit(debit);
      targetAccount.removeVirtualCredit(credit);
      invalidate();
   }

   public void startTransfer(){
      sourceAccount.performVirtualDebit(debit);
      targetAccount.performVirtualCredit(credit);
      invalidate();
   }

   private void checkTransferContext() {
      final String fn = "[checkTransferContext] ";
      if(sourceAccount == null || targetAccount == null || transferValue == null || transferValue.isNegative()){
         logger.warn(fn + "one of the given parameters was either NULL or the transfer value was negative");
         invalidate();
      }else{
         debit = new VirtualDebit(transferValue);
         credit = new VirtualCredit(transferValue);
         if(sourceAccount.addVirtualDebit(debit)){
            logger.debug(fn + "successfully initiated the transfer");
            targetAccount.addVirtualCredit(credit);
         }else{
            logger.warn(fn + "adding of the virtual debit wasn't successful!");
            invalidate();
         }
      }
   }

   public IFAccount getSourceAccount() {
      return sourceAccount;
   }

   public IFAccount getTargetAccount() {
      return targetAccount;
   }

   public IFAmount getTransferValue() {
      return transferValue;
   }

   public boolean isValid() {
      return valid;
   }

   private void invalidate(){
      sourceAccount = null;
      targetAccount = null;
      transferValue = null;
      debit = null;
      credit = null;
      valid = false;
   }
}
