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

import org.apache.log4j.Logger;
import junit.framework.TestCase;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.digestAgreement.IFDigestAgreementRequest;
import de.tu_dresden.diplom.richter_mirko_mat2628335.witness.DTWitness;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.digestAgreement.DigestAgreementRequest;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.evidence.BodyEvidence;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.account.Amount;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.account.IFAmount;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.account.IFCurrency;
import de.tu_dresden.diplom.richter_mirko_mat2628335.witness.account.AccountPool;
import de.tu_dresden.diplom.richter_mirko_mat2628335.witness.process.result.IFDigestAgreementConfirmationResult;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.entity.IFEntity;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.context.CoordinationContext;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.context.IFCoordinationContext;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.dependency.SOAPDependency;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.digestAgreement.DigestAgreementRequest;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.account.Amount;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.account.IFCurrency;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.entity.IFEntity;

/**
 * 
 */
public class UTDigestAgreementProcess extends TestCase{

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

   public void testSuccessfulConfirmation(){
      IFCoordinationContext refCtx = DTWitness.getCoordinationContextOne();
      IFDigestAgreementRequest reqOne = DTWitness.getDigestAgreementRequest(refCtx);
      IFEntity reqOneEntity = DTWitness.getClient1();
      IFDigestAgreementRequest reqTwo = DTWitness.getDigestAgreementRequest(refCtx);
      IFEntity reqTwoEntity = DTWitness.getClient1();
      IFWitnessContextInfo ctx = DTWitness.getContextInfo(refCtx);
      DigestAgreementProcess process = new DigestAgreementProcess(ctx);
      process.setFirst(reqOne, reqOneEntity, new BodyEvidence(null));
      assertEquals(process.getConfirmationResult(reqOne).getResultCode(), IFDigestAgreementConfirmationResult.WAITING_FOR_SECOND_REQUEST);
      process.setSecond(reqTwo, reqTwoEntity, new BodyEvidence(null));
      assertTrue(process.getConfirmationResult(reqOne).isSuccess());
      assertTrue(process.getConfirmationResult(reqTwo).isSuccess());
   }

   public void testDifferentCommStepConfirmation(){
      IFCoordinationContext refCtx = DTWitness.getCoordinationContextOne();
      DigestAgreementRequest reqOne = (DigestAgreementRequest) DTWitness.getDigestAgreementRequest(refCtx);
      IFEntity reqOneEntity = DTWitness.getClient1();
      DigestAgreementRequest reqTwo = (DigestAgreementRequest) DTWitness.getDigestAgreementRequest(refCtx);
      IFEntity reqTwoEntity = DTWitness.getClient1();
      IFWitnessContextInfo ctx = DTWitness.getContextInfo(refCtx);
      DigestAgreementProcess process = new DigestAgreementProcess(ctx);
      reqOne.setPhase(DigestAgreementRequest.PHASE_REQUEST);
      reqTwo.setPhase(DigestAgreementRequest.PHASE_RESPONSE);
      process.setFirst(reqOne, reqOneEntity, new BodyEvidence(null));
      process.setSecond(reqTwo, reqTwoEntity, new BodyEvidence(null));
      assertFalse(process.getConfirmationResult(reqOne).isSuccess());
      assertFalse(process.getConfirmationResult(reqTwo).isSuccess());
      assertEquals(process.getConfirmationResult(reqOne).getResultCode(), IFDigestAgreementConfirmationResult.REQUESTS_BELONG_TO_DIFFERENT_COMM_STEPS);
      assertEquals(process.getConfirmationResult(reqTwo).getResultCode(), IFDigestAgreementConfirmationResult.REQUESTS_BELONG_TO_DIFFERENT_COMM_STEPS);
   }

   public void testDifferentAmountConfirmation(){
      IFCoordinationContext refCtx = DTWitness.getCoordinationContextOne();
      DigestAgreementRequest reqOne = (DigestAgreementRequest) DTWitness.getDigestAgreementRequest(refCtx);
      IFEntity reqOneEntity = DTWitness.getClient1();
      DigestAgreementRequest reqTwo = (DigestAgreementRequest) DTWitness.getDigestAgreementRequest(refCtx);
      IFEntity reqTwoEntity = DTWitness.getClient1();
      IFWitnessContextInfo ctx = DTWitness.getContextInfo(refCtx);
      DigestAgreementProcess process = new DigestAgreementProcess(ctx);
      reqOne.setAmount(new Amount(100, IFCurrency.CURRENCY_COUNTER_INST));
      process.setFirst(reqOne, reqOneEntity, new BodyEvidence(null));
      process.setSecond(reqTwo, reqTwoEntity, new BodyEvidence(null));
      assertFalse(process.getConfirmationResult(reqOne).isSuccess());
      assertFalse(process.getConfirmationResult(reqTwo).isSuccess());
      assertEquals(process.getConfirmationResult(reqOne).getResultCode(), IFDigestAgreementConfirmationResult.AMOUNTS_DIFFER);
      assertEquals(process.getConfirmationResult(reqTwo).getResultCode(), IFDigestAgreementConfirmationResult.AMOUNTS_DIFFER);

      // switch request order (should not matter)
      process.setFirst(reqTwo, reqTwoEntity, new BodyEvidence(null));
      process.setSecond(reqOne, reqOneEntity, new BodyEvidence(null));
      assertFalse(process.getConfirmationResult(reqOne).isSuccess());
      assertFalse(process.getConfirmationResult(reqTwo).isSuccess());
      assertEquals(process.getConfirmationResult(reqOne).getResultCode(), IFDigestAgreementConfirmationResult.AMOUNTS_DIFFER);
      assertEquals(process.getConfirmationResult(reqTwo).getResultCode(), IFDigestAgreementConfirmationResult.AMOUNTS_DIFFER);

      // equal
      process = new DigestAgreementProcess(ctx);
      reqOne.setAmount(new Amount(100, IFCurrency.CURRENCY_COUNTER_INST));
      reqTwo.setAmount(new Amount(100, IFCurrency.CURRENCY_COUNTER_INST));
      process.setFirst(reqOne, reqOneEntity, new BodyEvidence(null));
      process.setSecond(reqTwo, reqTwoEntity, new BodyEvidence(null));
      assertTrue(process.getConfirmationResult(reqOne).isSuccess());
      assertTrue(process.getConfirmationResult(reqTwo).isSuccess());

      // differ in amount
      process = new DigestAgreementProcess(ctx);
      reqOne.setAmount(new Amount(101, IFCurrency.CURRENCY_COUNTER_INST));
      reqTwo.setAmount(new Amount(100, IFCurrency.CURRENCY_COUNTER_INST));
      process.setFirst(reqOne, reqOneEntity, new BodyEvidence(null));
      process.setSecond(reqTwo, reqTwoEntity, new BodyEvidence(null));
      assertFalse(process.getConfirmationResult(reqOne).isSuccess());
      assertFalse(process.getConfirmationResult(reqTwo).isSuccess());
      assertEquals(process.getConfirmationResult(reqOne).getResultCode(), IFDigestAgreementConfirmationResult.AMOUNTS_DIFFER);
      assertEquals(process.getConfirmationResult(reqTwo).getResultCode(), IFDigestAgreementConfirmationResult.AMOUNTS_DIFFER);

      //differ in currency
      process = new DigestAgreementProcess(ctx);
      reqOne.setAmount(new Amount(100, IFCurrency.CURRENCY_EURO_INST));
      reqTwo.setAmount(new Amount(100, IFCurrency.CURRENCY_COUNTER_INST));
      process.setFirst(reqOne, reqOneEntity, new BodyEvidence(null));
      process.setSecond(reqTwo, reqTwoEntity, new BodyEvidence(null));
      assertFalse(process.getConfirmationResult(reqOne).isSuccess());
      assertFalse(process.getConfirmationResult(reqTwo).isSuccess());
      assertEquals(process.getConfirmationResult(reqOne).getResultCode(), IFDigestAgreementConfirmationResult.AMOUNTS_DIFFER);
      assertEquals(process.getConfirmationResult(reqTwo).getResultCode(), IFDigestAgreementConfirmationResult.AMOUNTS_DIFFER);

      //differ in amount and currency
      process = new DigestAgreementProcess(ctx);
      reqOne.setAmount(new Amount(100, IFCurrency.CURRENCY_EURO_INST));
      reqTwo.setAmount(new Amount(101, IFCurrency.CURRENCY_COUNTER_INST));
      process.setFirst(reqOne, reqOneEntity, new BodyEvidence(null));
      process.setSecond(reqTwo, reqTwoEntity, new BodyEvidence(null));
      assertFalse(process.getConfirmationResult(reqOne).isSuccess());
      assertFalse(process.getConfirmationResult(reqTwo).isSuccess());
      assertEquals(process.getConfirmationResult(reqOne).getResultCode(), IFDigestAgreementConfirmationResult.AMOUNTS_DIFFER);
      assertEquals(process.getConfirmationResult(reqTwo).getResultCode(), IFDigestAgreementConfirmationResult.AMOUNTS_DIFFER);

   }

   public void testDifferentDigestConfirmation(){
      AccountPool.resetAccounts();
      IFCoordinationContext refCtx = DTWitness.getCoordinationContextOne();
      DigestAgreementRequest reqOne = (DigestAgreementRequest) DTWitness.getDigestAgreementRequest(refCtx);
      IFEntity reqOneEntity = DTWitness.getClient1();
      DigestAgreementRequest reqTwo = (DigestAgreementRequest) DTWitness.getDigestAgreementRequest(refCtx);
      IFEntity reqTwoEntity = DTWitness.getClient1();
      IFWitnessContextInfo ctx = DTWitness.getContextInfo(refCtx);
      DigestAgreementProcess process = new DigestAgreementProcess(ctx);
      reqOne.setDigest("one");
      reqTwo.setDigest("another");
      process.setFirst(reqOne, reqOneEntity, new BodyEvidence(null));
      process.setSecond(reqTwo, reqTwoEntity, new BodyEvidence(null));
      assertFalse(process.getConfirmationResult(reqOne).isSuccess());
      assertFalse(process.getConfirmationResult(reqTwo).isSuccess());
      assertEquals(process.getConfirmationResult(reqOne).getResultCode(), IFDigestAgreementConfirmationResult.DIGEST_MATCH_FAILURE);
      assertEquals(process.getConfirmationResult(reqTwo).getResultCode(), IFDigestAgreementConfirmationResult.DIGEST_MATCH_FAILURE);

      reqOne.setDigest(null);
      reqTwo.setDigest("another");
      process.setFirst(reqOne, reqOneEntity, new BodyEvidence(null));
      process.setSecond(reqTwo, reqTwoEntity, new BodyEvidence(null));
      assertFalse(process.getConfirmationResult(reqOne).isSuccess());
      assertFalse(process.getConfirmationResult(reqTwo).isSuccess());
      assertEquals(process.getConfirmationResult(reqOne).getResultCode(), IFDigestAgreementConfirmationResult.DIGEST_MATCH_FAILURE);
      assertEquals(process.getConfirmationResult(reqTwo).getResultCode(), IFDigestAgreementConfirmationResult.DIGEST_MATCH_FAILURE);

      reqOne.setDigest("one");
      reqTwo.setDigest(null);
      process.setFirst(reqOne, reqOneEntity, new BodyEvidence(null));
      process.setSecond(reqTwo, reqTwoEntity, new BodyEvidence(null));
      assertFalse(process.getConfirmationResult(reqOne).isSuccess());
      assertFalse(process.getConfirmationResult(reqTwo).isSuccess());
      assertEquals(process.getConfirmationResult(reqOne).getResultCode(), IFDigestAgreementConfirmationResult.DIGEST_MATCH_FAILURE);
      assertEquals(process.getConfirmationResult(reqTwo).getResultCode(), IFDigestAgreementConfirmationResult.DIGEST_MATCH_FAILURE);

      reqOne.setDigest(null);
      reqTwo.setDigest(null);
      process.setFirst(reqOne, reqOneEntity, new BodyEvidence(null));
      process.setSecond(reqTwo, reqTwoEntity, new BodyEvidence(null));
      assertTrue(process.getConfirmationResult(reqOne).isSuccess());
      assertTrue(process.getConfirmationResult(reqTwo).isSuccess());
   }

   public void testCrossConfirmationFailures(){
      IFCoordinationContext refCtx = DTWitness.getCoordinationContextOne();
      DigestAgreementRequest reqOne = (DigestAgreementRequest) DTWitness.getDigestAgreementRequest(refCtx);
      IFEntity reqOneEntity = DTWitness.getClient1();
      DigestAgreementRequest reqTwo = (DigestAgreementRequest) DTWitness.getDigestAgreementRequest(refCtx);
      IFEntity reqTwoEntity = DTWitness.getClient1();
      IFWitnessContextInfo ctx = DTWitness.getContextInfo(refCtx);
      DigestAgreementProcess process = new DigestAgreementProcess(ctx);
      reqOne.setDigest(null);
      reqTwo.setDigest("another");
      reqOne.setAmount(new Amount(100, IFCurrency.CURRENCY_COUNTER_INST));
      reqTwo.setDependency(new SOAPDependency());
      process.setFirst(reqOne, reqOneEntity, new BodyEvidence(null));
      process.setSecond(reqTwo, reqTwoEntity, new BodyEvidence(null));
      assertFalse(process.getConfirmationResult(reqOne).isSuccess());
      assertFalse(process.getConfirmationResult(reqTwo).isSuccess());
   }

}
