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

import org.apache.log4j.Logger;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.context.IFCoordinationContext;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.context.BaseContextInfo;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.entity.IFEntity;
import de.tu_dresden.diplom.richter_mirko_mat2628335.witness.account.IFAccountTransferContext;
import de.tu_dresden.diplom.richter_mirko_mat2628335.witness.account.IFAccount;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.entity.IFEntity;
import de.tu_dresden.diplom.richter_mirko_mat2628335.witness.dependency.IFDependencyManager;
import de.tu_dresden.diplom.richter_mirko_mat2628335.witness.dependency.DependencyManager;
import de.tu_dresden.diplom.richter_mirko_mat2628335.witness.context.ex.ContextInfoInvalidException;

import java.util.Map;
import java.util.HashMap;

/**
 * 
 */
public class WitnessContextInfo extends BaseContextInfo implements IFWitnessContextInfo{

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

   private boolean invalid = false;
   private String invalidityReason = null;

   private IFCoordinationContext coordinationContextObject = null;
   private IFAccount sourceAccount = null;
   private IFEntity owningEntity = null;
   private boolean successfullCreated = false;
   private IFDependencyManager dependencyManager = null;

   /**
    * If a request is confirmed by an successful performed digestAgreement-process
    * an AccountTransferContext is created pointing from the source account to the
    * target account (and vica versa).<br/>
    * The AccountTransferContext guarantees that the source account has enough
    * "money" to perform the action. 
    */
   private Map accountTransferContexts = null;

   /**
    * Mapping from ident-String to all open digestAgreement processes
    * currently open within this contextInfo
    */
   private Map digestAgreementProcesses = null;

   public WitnessContextInfo() {
      dependencyManager = new DependencyManager();
      digestAgreementProcesses = new HashMap();
      accountTransferContexts = new HashMap();
   }

   public void setContextObject(IFCoordinationContext coordinationContextObject) throws ContextInfoInvalidException {
      checkForInvalidity();
      this.coordinationContextObject = coordinationContextObject;
   }

   public IFCoordinationContext getContextObject() throws ContextInfoInvalidException {
      checkForInvalidity();
      return coordinationContextObject;
   }

   public void setSourceAccount(IFAccount sourceAccount) throws ContextInfoInvalidException {
      checkForInvalidity();
      this.sourceAccount = sourceAccount;
   }

   public IFAccount getSourceAccount() throws ContextInfoInvalidException {
      checkForInvalidity();
      return sourceAccount;
   }

   public IFEntity getOwningEntity() throws ContextInfoInvalidException {
      checkForInvalidity();
      return owningEntity;
   }

   public void setOwningEntity(IFEntity owningEntity) throws ContextInfoInvalidException {
      checkForInvalidity();
      this.owningEntity = owningEntity;
   }

   public boolean isSuccessfulCreated() throws ContextInfoInvalidException {
      checkForInvalidity();
      return successfullCreated;
   }

   public void setSuccessfullCreated(boolean successfullCreated) throws ContextInfoInvalidException {
      checkForInvalidity();
      this.successfullCreated = successfullCreated;
   }

   public String toString() {
      StringBuffer result = new StringBuffer("[WitnessContextInfo::");
      try {
         result.append(" successfullCreated=").append(isSuccessfulCreated());
         result.append(" | coordinationContextObject=").append(getContextObject());
         result.append(" | sourceAccount=").append(getSourceAccount());
         result.append(" | owningEntity=").append(getOwningEntity());
      } catch (ContextInfoInvalidException e) {
         result.append("INVALID");
      }
      result.append("]");
      return result.toString();
   }

   public IFDependencyManager getDependencyManager() throws ContextInfoInvalidException {
      checkForInvalidity();
      return dependencyManager;
   }

   public IFDigestAgreementProcess getDigestAgreementProcess(String ident) throws ContextInfoInvalidException {
      checkForInvalidity();
      return (IFDigestAgreementProcess) digestAgreementProcesses.get(ident);
   }

   public void removeDigestAgreementProcess(String ident) throws ContextInfoInvalidException {
      checkForInvalidity();
      digestAgreementProcesses.remove(ident);
   }

   public void addDigestAgreementProcess(String ident, IFDigestAgreementProcess digAgreeProc) throws ContextInfoInvalidException {
      checkForInvalidity();
      digestAgreementProcesses.put(ident, digAgreeProc);
   }

   private void checkForInvalidity() throws ContextInfoInvalidException {
      if(isInvalid()){
         throw new ContextInfoInvalidException(invalidityReason);
      }
   }

   public boolean isInvalid() {
      return invalid;
   }

   public void setInvalid(String invalidityReason) throws ContextInfoInvalidException {
      checkForInvalidity();
      this.invalid = true;
      this.invalidityReason = invalidityReason;
   }

   public String getInvalidityReason() {
      return invalidityReason;
   }

   public boolean hasOpenAccountTransferContexts() throws ContextInfoInvalidException {
      checkForInvalidity();
      return (accountTransferContexts.size() > 0);
   }

   public void addAccountTransferContext(String reference, IFAccountTransferContext accountTransferContext){
      final String fn = "[addAccountTransferContext] ";
      if(reference != null && accountTransferContext != null){
         accountTransferContexts.put(reference, accountTransferContext);
      }else{
         logger.warn(fn + "NULL PARAM NOT ALLOWED!");
      }
   }

   public IFAccountTransferContext getAccountTransferContext(String reference){
      return (IFAccountTransferContext) accountTransferContexts.get(reference);
   }

   public void removeAccountTransferContext(String reference){
      accountTransferContexts.remove(reference);
   }

   public String getIdentification(){
      String result = null;
      try {
         if(getContextObject() != null){
            result = getContextObject().getIdentification();
         }
      } catch (ContextInfoInvalidException e) {
         e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
      }
      return result;
   }

}
