//==============================================================================
//The Society of Actuaries (SOA) makes this computer model and its computer
//code available to its members for educational purposes. The model and its
//code may be modified and redistributed without prior authorization from the
//SOA. The SOA distributes this computer model and its computer code in the
//hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
//implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
//PURPOSE.
//==============================================================================
package agents;

import java.util.ArrayList;
import java.util.Collections;
import java.util.ListIterator;
import repast.simphony.context.Context;
import repast.simphony.engine.environment.RunEnvironment;
import repast.simphony.parameter.Parameter;
import repast.simphony.random.RandomHelper;
import repast.simphony.space.continuous.ContinuousSpace;
import repast.simphony.ui.probe.ProbeID;
import resources.AgentID;
import resources.Constants;
import resources.Constants.PlanPresentationOrder;
import resources.InsurancePlan;
import resources.Premium;
import agents.Agent;

@SuppressWarnings("unused")
public class Exchange extends Agent
{
//==============================================================================
// Attribute variables
// These variables do not change during the agent's life (unless the user
// changes an attribute parameter during a simulation).
//------------------------------------------------------------------------------
    private PlanPresentationOrder planPresentationOrder;
    private double advertisingExpensePercentage;
    private double uninsuredDecreaseTarget;

//==============================================================================


//==============================================================================
// Memory variables
// These variables can change during an agent's life.
// There are two types of memory variables:
// 1. Currently updated variables:  Variables that the agent updates during the
//    period to which they apply.
// 2. Previously updated variables:  Variables that the agent updates during the
//    period prior to the period in which they apply.
//------------------------------------------------------------------------------

    //1. Currently updated memory variables
    // Variables from p1_OfferPlans()
    ArrayList<Premium> premiumList = new ArrayList<Premium>();
    private double currentPremium_PlanA1;
    private double currentPremium_PlanA2;
    private double currentCopaymentPercentage_PlanA2;
    private double currentPremium_PlanB1;
    private double currentPremium_PlanB2;
    private double currentCopaymentPercentage_PlanB2;

    // Variables from p2_AdvertisePlans()
    private int currentAdvertisingIntensity;
    private int priorAdvertisingIntensity;
    private double priorUninsuredPercentage;
    boolean currentUninsuredGoalAchieved;

    // Variables from p3_TransferPremiums()
    private double currentPremiumsReceived_PlanA1;
    private double currentPremiumsReceived_PlanA2;
    private double currentPremiumsReceived_PlanB1;
    private double currentPremiumsReceived_PlanB2;
    private double currentAdvertisingExpenses_PlanA1;
    private double currentAdvertisingExpenses_PlanA2;
    private double currentAdvertisingExpenses_PlanB1;
    private double currentAdvertisingExpenses_PlanB2;
    private double currentPremiumsTransferred_PlanA1;
    private double currentPremiumsTransferred_PlanA2;
    private double currentPremiumsTransferred_PlanB1;
    private double currentPremiumsTransferred_PlanB2;

    //2. Previously updated memory variables
    //None

//==============================================================================


//==============================================================================
// Other variables
// These are other variables used in the class, or required by other classes.
//------------------------------------------------------------------------------
    private ContinuousSpace<Object> communitySpace;
    private Context<Object> simulationContext;

    private double tickCount;

//==============================================================================


//==============================================================================
// Method:  Exchange() constructor
//------------------------------------------------------------------------------

    public Exchange(ContinuousSpace<Object> pCommunitySpace, Context<Object> pContext, AgentID pExchangeID)
    {

        setAgentID(pExchangeID);
        communitySpace = pCommunitySpace;
        simulationContext = pContext;

        init_InitializeVariables_Constructor();
        
    }//end Exchange()

//==============================================================================


//==============================================================================
// Methods: Initialization methods for the agent. These are used in
//          the agent's constructor method or at the beginning of each
//          simulation period.
//==============================================================================

//==============================================================================
// Method:  init_InitializeVariables_Constructor()
// The constructor does the following:
// 1. Initializes variables that remain constant throughout
//    an agent's life (unless the user changes parameters).
//    These are the agent's "attribute" variables.
// 2. Initializes the value of all other variables.
// This method gives a valid (non-null) value to all the agent's variables.
//------------------------------------------------------------------------------
    private void init_InitializeVariables_Constructor()
    {

        // 1. Initialize "attribute" variables.
        planPresentationOrder = Environment.getExchange_PlanPresentationOrder();
        advertisingExpensePercentage = Environment.getExchange_AdvertisingExpensePercentage();
        uninsuredDecreaseTarget = Environment.getExchange_UninsuredDecreaseTarget();

        // 2. Initialize the value of all other variables.
        currentPremium_PlanA1 = 0.0;
        currentPremium_PlanA2 = 0.0;
        currentCopaymentPercentage_PlanA2 = 0.0;
        currentPremium_PlanB1 = 0.0;
        currentPremium_PlanB2 = 0.0;
        currentCopaymentPercentage_PlanB2 = 0.0;
        currentAdvertisingIntensity = 0;
        priorAdvertisingIntensity = 0;
        priorUninsuredPercentage = 0.0;
        currentUninsuredGoalAchieved = false;

        currentPremiumsReceived_PlanA1= 0.0;
        currentPremiumsReceived_PlanA2= 0.0;
        currentPremiumsReceived_PlanB1= 0.0;
        currentPremiumsReceived_PlanB2= 0.0;

        currentAdvertisingExpenses_PlanA1= 0.0;
        currentAdvertisingExpenses_PlanA2= 0.0;
        currentAdvertisingExpenses_PlanB1= 0.0;
        currentAdvertisingExpenses_PlanB2= 0.0;

        currentPremiumsTransferred_PlanA1= 0.0;
        currentPremiumsTransferred_PlanA2= 0.0;
        currentPremiumsTransferred_PlanB1= 0.0;
        currentPremiumsTransferred_PlanB2= 0.0;

        // Set up and initialize the premium list
        // The order of the premium list is the order in which they will be
        // displayed on the Exchange web site.
        for (int i = 0; i < Constants.NUMBER_OF_HEALTH_INSURANCE_PLANS; i++)
        {
            Premium premium = new Premium();
            premium.setInsurancePlanIndex(i);
            premium.setPremiumAmount(Environment.getInsurancePlanList().get(i).getCurrentPremiumAmount());
            premiumList.add(premium);

            switch (i)
            {
                case Constants.PLAN_A1:
                {
                    currentPremium_PlanA1 = Environment.getInsurancePlanList().get(i).getCurrentPremiumAmount();
                    break;
                }//end case

                case Constants.PLAN_A2:
                {
                    currentPremium_PlanA2 = Environment.getInsurancePlanList().get(i).getCurrentPremiumAmount();
                    currentCopaymentPercentage_PlanA2 = Environment.getInsurancePlanList().get(i).getCopaymentPercentage();
                    break;
                }//end case
                case Constants.PLAN_B1:
                {
                    currentPremium_PlanB1 = Environment.getInsurancePlanList().get(i).getCurrentPremiumAmount();
                    break;
                }//end case
                case Constants.PLAN_B2:
                {
                    currentPremium_PlanB2 = Environment.getInsurancePlanList().get(i).getCurrentPremiumAmount();
                    currentCopaymentPercentage_PlanB2 = Environment.getInsurancePlanList().get(i).getCopaymentPercentage();
                    break;
                }//end case
                default:
                {
                // There should be no default
                    System.out.println("Error:  Unexpected switch default in Exchange init_InitializeVariables_Constructor()");
                }//end case

            }//end switch
        }//end for

    }//end init_InitializeVariables_Constructor()
//------------------------------------------------------------------------------

//==============================================================================
// Method:  init_InitializeVariables_BOP() (beginning of period)
// This method does the following:
// 1. Updates attribute variables. If the user changes an attribute parameter
//    during a simulation, these may change.
// 2. Updates the prior period values of all variables (after the first period).
// 3. Provides "current" values for certain variables that the agent
//    does not set at the beginning of the period with a separate behavior.
//    This is done for those variables will be needed by behaviors of this agent
//    or by other agents during the period.
// 4. Re-initialize all CURRENT (NOT PRIOR) variables (except those that would cause
//    display or chart problems (flickering, etc.).
// 5. removes agents that have died.
//------------------------------------------------------------------------------
    public void init_InitializeVariables_BOP()
    {

        // 1. Update attribute variables.
        planPresentationOrder = Environment.getExchange_PlanPresentationOrder();
        advertisingExpensePercentage = Environment.getExchange_AdvertisingExpensePercentage();
        uninsuredDecreaseTarget = Environment.getExchange_UninsuredDecreaseTarget();

        // 2. Update prior period values of all variables (after the first period).
        tickCount = RunEnvironment.getInstance().getCurrentSchedule().getTickCount();
        if (tickCount >= 1.0)
        {
            priorAdvertisingIntensity = currentAdvertisingIntensity;
        }//end if

        // 3. Provide "current" values for certain variables that the agent does not set at the
        //    beginning of the period with a separate behavior.
        // None

        // 4. Re-initialize all CURRENT (NOT PRIOR) variables (except those that would cause
        //    display or chart problems (flickering, etc.).
        currentPremium_PlanA1 = 0.0;
        currentPremium_PlanA2 = 0.0;
        currentCopaymentPercentage_PlanA2 = 0.0;
        currentPremium_PlanB1 = 0.0;
        currentPremium_PlanB2 = 0.0;
        currentCopaymentPercentage_PlanB2 = 0.0;
        currentAdvertisingIntensity = 0;
        priorUninsuredPercentage = 0.0; // This variable is recalculated during the period
        currentUninsuredGoalAchieved = false;

        currentPremiumsReceived_PlanA1= 0.0;
        currentPremiumsReceived_PlanA2= 0.0;
        currentPremiumsReceived_PlanB1= 0.0;
        currentPremiumsReceived_PlanB2= 0.0;

        currentAdvertisingExpenses_PlanA1= 0.0;
        currentAdvertisingExpenses_PlanA2= 0.0;
        currentAdvertisingExpenses_PlanB1= 0.0;
        currentAdvertisingExpenses_PlanB2= 0.0;

        currentPremiumsTransferred_PlanA1= 0.0;
        currentPremiumsTransferred_PlanA2= 0.0;
        currentPremiumsTransferred_PlanB1= 0.0;
        currentPremiumsTransferred_PlanB2= 0.0;

        // 4. Remove agents that have died
        // None

    }//end init_InitializeVariables_BOP()
//------------------------------------------------------------------------------

//==============================================================================


//==============================================================================
// Methods:  "Input" methods for the agent. These are described in the
// detailed description of the model. Each method is preceded by "i#".
//==============================================================================

// None

//==============================================================================


//==============================================================================
// Methods:  "Process" methods for the agent. These are described in the
// detailed description of the model. Each method is preceded by "p#"
// to indicate its number according to the numbering scheme used in the
// detailed description.
//==============================================================================

//==============================================================================
// Method:  p1_OfferPlans()
// The Exchange offers plans on its website according to the order determined
// by Rule 1 (Arrange plan order).
//------------------------------------------------------------------------------
    public void p1_OfferPlans()
    {

        r1_ArrangePlanOrder();

        // Determine the coordinates of the each plan for the display
        // and then display it.
        for (int n = 0; n < Constants.NUMBER_OF_HEALTH_INSURANCE_PLANS; n++)
        {

            double xCoordinate = 0.0;
            double yCoordinate = 63.0 - Environment.getInsurancePlanList().get(n).getCurrentExchangePresentationOrder()*8.0;

            Environment.getInsurancePlanList().get(n).setAgentXLocation(xCoordinate);
            Environment.getInsurancePlanList().get(n).setAgentYLocation(yCoordinate);
            communitySpace.moveTo(Environment.getInsurancePlanList().get(n), xCoordinate, yCoordinate);

        }//end for

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Test 
// This block tests this method.
// To run the test, remove comments from the code below.
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//    System.out.println("Exchange p1_OfferPlans() at " +
//            RunEnvironment.getInstance().getCurrentSchedule().getTickCount());
//
//    for (int p = 0; p < Constants.NUMBER_OF_HEALTH_INSURANCE_PLANS; p++)
//    {
//        InsurancePlan insurancePlan2 = Environment.getInsurancePlanList().get(p);
//        System.out.println("----------------");
//        System.out.println("Plan ID:  " + insurancePlan2.getAgentID().getAgentIDString());
//        System.out.println("getCurrentExchangePresentationOrder:  " + insurancePlan2.getCurrentExchangePresentationOrder());
//        System.out.println("getCurrentPremiumOrder_HighToLow:  " + insurancePlan2.getCurrentPremiumOrder_HighToLow());
//        System.out.println("xLocation:  " + insurancePlan2.getAgentXLocation());
//        System.out.println("yLocation:  " + insurancePlan2.getAgentYLocation());
//        System.out.println("currentPremiumAmount:  " + insurancePlan2.getCurrentPremiumAmount());
//        System.out.println("priorPremiumAmount:  " + insurancePlan2.getPriorPremiumAmount());
//        System.out.println("copaymentPercentage_Plan2:  " + insurancePlan2.getCopaymentPercentage());
//    }//end for
//
//    for (int q = 0; q < Constants.NUMBER_OF_HEALTH_INSURANCE_PLANS; q++)
//    {
//        Premium premium2 = premiumList.get(q);
//        System.out.println("----------------");
//        System.out.println("insurancePlanIndex  " + premium2.getInsurancePlanIndex());
//        System.out.println("premiumAmount  " + premium2.getPremiumAmount());
//
//    }//end for
//
//      System.out.println("--------------------------------------");
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    }//end p1_OfferPlans()
//------------------------------------------------------------------------------

//==============================================================================
// Method:  p2_AdvertisePlans()
// The Exchange produces advertising, with an advertising intensity equal to
// the result of Rule 2 (Determine advertising intensity).
//------------------------------------------------------------------------------
    public void p2_AdvertisePlans()
    {

        tickCount = RunEnvironment.getInstance().getCurrentSchedule().getTickCount();
        if (tickCount < 1.0 )
        {
            currentAdvertisingIntensity = Environment.getExchange_InitialAdvertisingIntensity();
        }//end if

        else r2_DetermineAdvertisingIntensity();
        
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Test 
// This block tests this method.
// To run the test, remove comments from the code below.
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//    System.out.println("Exchange p2_AdvertisePlans() at " +
//            RunEnvironment.getInstance().getCurrentSchedule().getTickCount());
//
//    System.out.println("currentAdvertisingIntensity:  " + currentAdvertisingIntensity);
//    System.out.println("priorAdvertisingIntensity:  " + priorAdvertisingIntensity);    
//
//    System.out.println("--------------------------------------");    
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++        

    }//end p2_AdvertisePlans()
//------------------------------------------------------------------------------

//==============================================================================
// Method:  p3_TransferPremiums()
// The Exchange transfers an amount to each Health Insurance Company, equal to
//  the amount of premiums received for the company’s plans, min
// Rule 3 (Determine advertising expenses).
//------------------------------------------------------------------------------
    public void p3_TransferPremiums()
    {

        ListIterator<Person> iterator1 = Environment.getPersonList().listIterator();
        currentPremiumsReceived_PlanA1 = 0.0;
        currentPremiumsReceived_PlanA2 = 0.0;
        currentPremiumsReceived_PlanB1 = 0.0;
        currentPremiumsReceived_PlanB2 = 0.0;

        while (iterator1.hasNext())
        {
            Person person = iterator1.next();
            switch (person.getCurrentPlanChosen())
            {
                case PlanA1:
                {
                    currentPremiumsReceived_PlanA1 =
                            currentPremiumsReceived_PlanA1 + Environment.getInsurancePlanList().get(Constants.PLAN_A1).getCurrentPremiumAmount();
                    break;
                }//end case
                case PlanA2:
                {
                    currentPremiumsReceived_PlanA2 =
                            currentPremiumsReceived_PlanA2 + Environment.getInsurancePlanList().get(Constants.PLAN_A2).getCurrentPremiumAmount();
                    break;
                }//end case
                case PlanB1:
                {
                    currentPremiumsReceived_PlanB1 =
                            currentPremiumsReceived_PlanB1 + Environment.getInsurancePlanList().get(Constants.PLAN_B1).getCurrentPremiumAmount();
                    break;
                }//end case
                case PlanB2:
                {
                    currentPremiumsReceived_PlanB2 =
                            currentPremiumsReceived_PlanB2 + Environment.getInsurancePlanList().get(Constants.PLAN_B2).getCurrentPremiumAmount();
                    break;
                }//end case
                case None:
                {
                    // Do nothing
                    break;
                }//end case
                default:
                {
                // There should be no default
                    System.out.println("Error:  Unexpected switch default in Exchange p3_TransferPremiums()");
                }//end case

            }//end switch

        }//end while

        r3_DetermineAdvertisingExpenses();

        currentPremiumsTransferred_PlanA1 = currentPremiumsReceived_PlanA1 - currentAdvertisingExpenses_PlanA1;
        currentPremiumsTransferred_PlanA2 = currentPremiumsReceived_PlanA2 - currentAdvertisingExpenses_PlanA2;
        currentPremiumsTransferred_PlanB1 = currentPremiumsReceived_PlanB1 - currentAdvertisingExpenses_PlanB1;
        currentPremiumsTransferred_PlanB2 = currentPremiumsReceived_PlanB2 - currentAdvertisingExpenses_PlanB2;

    }//end p3_TransferPremiums()
//------------------------------------------------------------------------------

//==============================================================================


//==============================================================================
// Methods:  "Rule" methods for the agent. These are described in the
// detailed description of the model. Each method is preceded by "r#"
// to indicate its number according to the numbering scheme used in the
// detailed description.
//==============================================================================

//==============================================================================
// Method:  r1_ArrangePlanOrder()
// Based on the parameter D1 on the parameter pane, the Exchange determines
// the order in which it will offer plans on the Exchange website.
//------------------------------------------------------------------------------
    private void r1_ArrangePlanOrder()
    {

        // Determine the current order of premiums.
        for (int i = 0; i < premiumList.size(); i++)
        {
            premiumList.get(i).setInsurancePlanIndex(i);
            premiumList.get(i).setPremiumAmount(Environment.getInsurancePlanList().get(i).getCurrentPremiumAmount());
            switch (i)
            {
                case Constants.PLAN_A1:
                {
                    currentPremium_PlanA1 = Environment.getInsurancePlanList().get(i).getCurrentPremiumAmount();
                    break;
                }//end case

                case Constants.PLAN_A2:
                {
                    currentPremium_PlanA2 = Environment.getInsurancePlanList().get(i)
                            .getCurrentPremiumAmount();
                    currentCopaymentPercentage_PlanA2 = Environment.getInsurancePlanList().get(i)
                            .getCopaymentPercentage();
                    break;
                }//end case
                case Constants.PLAN_B1:
                {
                    currentPremium_PlanB1 = Environment.getInsurancePlanList().get(i).getCurrentPremiumAmount();
                    break;
                }//end case
                case Constants.PLAN_B2:
                {
                    currentPremium_PlanB2 = Environment.getInsurancePlanList().get(i)
                            .getCurrentPremiumAmount();
                    currentCopaymentPercentage_PlanB2 = Environment.getInsurancePlanList().get(i)
                            .getCopaymentPercentage();
                    break;
                }//end case
                default:
                {
                // There should be no default
                    System.out.println("Error:  Unexpected switch default in Exchange r1_ArrangePlanOrder()");
                }//end case

            }//end switch

        }//end for


        Collections.sort(premiumList);
        
        for (int j = 0; j < Constants.NUMBER_OF_HEALTH_INSURANCE_PLANS; j++)
        {
            Environment.getInsurancePlanList().get(premiumList.get(j).getInsurancePlanIndex()).setCurrentPremiumOrder_HighToLow(j);
        }//end for


        switch (Environment.getExchange_PlanPresentationOrder())
        {

            case LowToHighPremium:
            {
                for (int k = 0; k < Constants.NUMBER_OF_HEALTH_INSURANCE_PLANS; k++)
                {
                    Environment.getInsurancePlanList().get(k).setCurrentExchangePresentationOrder
                        (3 - Environment.getInsurancePlanList().get(k).getCurrentPremiumOrder_HighToLow());
                }//end for
                break;
            }//end case

            case HighToLowPremium:
            {
                for (int k = 0; k < Constants.NUMBER_OF_HEALTH_INSURANCE_PLANS; k++)
                {
                    Environment.getInsurancePlanList().get(k).setCurrentExchangePresentationOrder
                        (Environment.getInsurancePlanList().get(k).getCurrentPremiumOrder_HighToLow());
                }//end for
                break;
            }//end case

            case Random:
            {
                ArrayList<Integer> randomNumberList = new ArrayList<Integer>();

                while (randomNumberList.size() < 4)
                {
                    int randomNumber = RandomHelper.nextIntFromTo(0, 3);
                    
                    boolean match = false;
                    if (randomNumberList.size() == 0) randomNumberList.add(randomNumber);
                    else
                    {

                        for (int i = 0; i < randomNumberList.size(); i++)
                        {
                            if (randomNumber == randomNumberList.get(i)) match = true;
                        }//end for
                        
                        if (match == false) randomNumberList.add(randomNumber);
                        
                    }//end else
                    
                }//end while

                for (int m = 0; m < Constants.NUMBER_OF_HEALTH_INSURANCE_PLANS; m++)
                {
                    Environment.getInsurancePlanList().get(m).setCurrentExchangePresentationOrder(randomNumberList.get(m));
                }//end for
                
                break;
            }//end case

            default:
            {
            // There should be no default
                System.out.println("Error:  Unexpected switch default in Exchange r1_ArrangePlanOrder()");
            }//end case

        }//end switch

    }//end r1_ArrangePlanOrder()
//------------------------------------------------------------------------------

//==============================================================================
// Method:  r2_DetermineAdvertisingIntensity()
// If the Exchange has not reached its goal, it increases its advertising
// intensity each period by 1, up to the maximum advertising intensity of 10.
// If the Exchange has attained its goal, it does not change its
// advertising intensity.
//------------------------------------------------------------------------------
    private void r2_DetermineAdvertisingIntensity()
    {

        ListIterator<Person> iterator1 = Environment.getPersonList().listIterator();
        int numberOfLivingPersonAgents = 0;
        int numberOfCoveredPersonAgents = 0;

        while (iterator1.hasNext())
        {
            Person person = iterator1.next();
            numberOfCoveredPersonAgents = numberOfCoveredPersonAgents + (person.isPriorExchangeParticipationStatus() ? 1: 0);
            numberOfLivingPersonAgents = numberOfLivingPersonAgents + 1;

        }//end while

        if (numberOfLivingPersonAgents == 0) priorUninsuredPercentage = 1.0;
        else priorUninsuredPercentage = 1.0 - ((double) numberOfCoveredPersonAgents/ (double) numberOfLivingPersonAgents);
        
        if (1.0 - priorUninsuredPercentage < uninsuredDecreaseTarget)
        {
            currentAdvertisingIntensity = Math.min(priorAdvertisingIntensity + 1, Constants.MAXIMUM_ADVERTISING_INTENSITY);

        }//end if
        else
        {
            currentAdvertisingIntensity = priorAdvertisingIntensity;
            currentUninsuredGoalAchieved = true;
        }//end else

    }//end r2_DetermineAdvertisingIntensity()
//------------------------------------------------------------------------------

//==============================================================================
// Method:  r3_DetermineAdvertisingExpenses()
// The Exchange transfers an amount to each Health Insurance Company, equal to
// the amount of premiums received for the company’s plans, minus the Exchange’s
// advertising expenses for the year, calculated by
// Rule 3 (Determine advertising expenses).
//------------------------------------------------------------------------------
    private void r3_DetermineAdvertisingExpenses()
    {

        ListIterator<Person> iterator1 = Environment.getPersonList().listIterator();
        currentAdvertisingExpenses_PlanA1 = 0.0;
        currentAdvertisingExpenses_PlanA2 = 0.0;
        currentAdvertisingExpenses_PlanB1 = 0.0;
        currentAdvertisingExpenses_PlanB2 = 0.0;

        while (iterator1.hasNext())
        {
            Person person = iterator1.next();
            switch (person.getCurrentPlanChosen())
            {
                case PlanA1:
                {
                    currentAdvertisingExpenses_PlanA1 =
                            currentAdvertisingExpenses_PlanA1 + Environment.getInsurancePlanList().get(Constants.PLAN_A1)
                            .getCurrentPremiumAmount() * currentAdvertisingIntensity *advertisingExpensePercentage;
                    break;
                }//end case
                case PlanA2:
                {
                    currentAdvertisingExpenses_PlanA2 =
                            currentAdvertisingExpenses_PlanA2 + Environment.getInsurancePlanList().get(Constants.PLAN_A2)
                            .getCurrentPremiumAmount() * currentAdvertisingIntensity *advertisingExpensePercentage;
                    break;
                }//end case
                case PlanB1:
                {
                    currentAdvertisingExpenses_PlanB1 =
                            currentAdvertisingExpenses_PlanB1 + Environment.getInsurancePlanList().get(Constants.PLAN_B1)
                            .getCurrentPremiumAmount() * currentAdvertisingIntensity *advertisingExpensePercentage;
                    break;
                }//end case
                case PlanB2:
                {
                    currentAdvertisingExpenses_PlanB2 =
                            currentAdvertisingExpenses_PlanB2 + Environment.getInsurancePlanList().get(Constants.PLAN_B2)
                            .getCurrentPremiumAmount() * currentAdvertisingIntensity *advertisingExpensePercentage;
                    break;
                }//end case
                case None:
                {
                    // Do nothing
                    break;
                }//end case



                default:
                {
                // There should be no default
                    System.out.println("Error:  Unexpected switch default in Exchange r3_DetermineAdvertisingExpenses()");
                }//end case

            }//end switch

        }//end while

    }//end r3_DetermineAdvertisingExpenses()
//------------------------------------------------------------------------------

//==============================================================================


//==============================================================================
//Methods: "Probe" methods for the model user to probe the agent's data.
//Note:    As a simulation runs, the model user can probe an agent by
//	       double-clicking on its icon in the display. For more information
//	       about probes, see the Repast Simphony reference documentation.
//==============================================================================

// The "ProbeID" annotation provides the probe ID
    @ProbeID
    public String getName()
    {
        return getAgentName();
    }

    @Parameter (usageName="planPresentationOrder", displayName="A1. Plan presentation order")
    public String getPlanPresentationOrder()
    {
        switch(planPresentationOrder)
        {
            case LowToHighPremium:
            {
                return "Low to high premiums";
            }//end case
            
            case HighToLowPremium:
            {
                return "High to low premiums";
            }//end case
            
            case Random:
            {
                return "Random";
            }//end case
            
            default: return "Random";
        }//end switch

    }//end getPlanPresenationOrder()

    @Parameter (usageName="currentPremium_PlanA1", displayName="A2. Current premium - Plan A1")
    public double getCurrentPremium_PlanA1()
    {
        return currentPremium_PlanA1;
    }

    @Parameter (usageName="currentPremium_PlanA2", displayName="A3. Current premium - Plan A2")
    public double getCurrentPremium_PlanA2()
    {
        return currentPremium_PlanA2;
    }

    @Parameter (usageName="currentCopaymentPercentage_PlanA2", displayName="A4. Current copayment percentage - Plan A2")
    public double getCurrentCopaymentPercentage_PlanA2()
    {
        return currentCopaymentPercentage_PlanA2;
    }

    @Parameter (usageName="currentPremium_PlanB1", displayName="A5. Current premium - Plan B1")
    public double getCurrentPremium_PlanB1()
    {
        return currentPremium_PlanB1;
    }

    @Parameter (usageName="currentCopaymentPercentage_PlanB2", displayName="A6. Current copayment percentage - Plan B2")
    public double getCurrentPremium_PlanB2()
    {
        return currentPremium_PlanB2;
    }

    @Parameter (usageName="currentCopaymentPercentage_PlanB2", displayName="A7. Current copayment percentage - Plan B2")
    public double getCurrentCopaymentPercentage_PlanB2()
    {
        return currentCopaymentPercentage_PlanB2;
    }

    @Parameter (usageName="priorUninsuredPercentage", displayName="B1. Prior uninsured percentage")
    public double getPriorUninsuredPercentage()
    {
        return priorUninsuredPercentage;
    }

    @Parameter (usageName="uninsuredDecreaseTarget", displayName="B2. Uninsured decrease target")
    public double getUninsuredDecreaseTarget()
    {
        return uninsuredDecreaseTarget;
    }

    @Parameter (usageName="currentUninsuredGoalAchieved", displayName="B3. Uninsured goal achieved")
    public boolean isCurrentUninsuredGoalAchieved()
    {
        return currentUninsuredGoalAchieved;
    }

    @Parameter (usageName="currentAdvertisingIntensity", displayName="B4. Current advertising intensity")
    public int getCurrentAdvertisingIntensity()
    {
        return currentAdvertisingIntensity;
    }

    @Parameter (usageName="priorAdvertisingIntensity", displayName="B5. Prior advertising intensity")
    public int getPriorAdvertisingIntensity()
    {
        return priorAdvertisingIntensity;
    }

    @Parameter (usageName="currentPremiumsReceived_PlanA1", displayName="C1. Current premiums received - Plan A1")
    public double getCurrentPremiumsReceived_PlanA1()
    {
        return currentPremiumsReceived_PlanA1;
    }

    @Parameter (usageName="currentPremiumsReceived_PlanA2", displayName="C2. Current premiums received - Plan A2")
    public double getCurrentPremiumsReceived_PlanA2()
    {
        return currentPremiumsReceived_PlanA2;
    }

    @Parameter (usageName="currentPremiumsReceived_PlanB1", displayName="C3. Current premiums received - Plan B1")
    public double getCurrentPremiumsReceived_PlanB1()
    {
        return currentPremiumsReceived_PlanB1;
    }

    @Parameter (usageName="currentPremiumsReceived_PlanB2", displayName="C4. Current premiums received - Plan B2")
    public double getCurrentPremiumsReceived_PlanB2()
    {
        return currentPremiumsReceived_PlanB2;
    }

    @Parameter (usageName="currentAdvertisingExpenses_PlanA1", displayName="D1. Current advertising expenses - Plan A1")
    public double getCurrentAdvertisingExpenses_PlanA1()
    {
        return currentAdvertisingExpenses_PlanA1;
    }

    @Parameter (usageName="currentAdvertisingExpenses_PlanA2", displayName="D2. Current advertising expenses - Plan A2")
    public double getCurrentAdvertisingExpenses_PlanA2()
    {
        return currentAdvertisingExpenses_PlanA2;
    }

    @Parameter (usageName="currentAdvertisingExpenses_PlanB1", displayName="D3. Current advertising expenses - Plan B1")
    public double getCurrentAdvertisingExpenses_PlanB1()
    {
        return currentAdvertisingExpenses_PlanB1;
    }

    @Parameter (usageName="currentAdvertisingExpenses_PlanB2", displayName="D4. Current advertising expenses - Plan B2")
    public double getCurrentAdvertisingExpenses_PlanB2()
    {
        return currentAdvertisingExpenses_PlanB2;
    }

    @Parameter (usageName="currentPremiumsTransferred_PlanA1", displayName="E1. Current premiums transferred - Plan A1")
    public double getCurrentPremiumsTransferred_PlanA1()
    {
        return currentPremiumsTransferred_PlanA1;
    }

    @Parameter (usageName="currentPremiumsTransferred_PlanA2", displayName="E2. Current premiums transferred - Plan A2")
    public double getCurrentPremiumsTransferred_PlanA2()
    {
        return currentPremiumsTransferred_PlanA2;
    }

    @Parameter (usageName="currentPremiumsTransferred_PlanB1", displayName="E3. Current premiums transferred - Plan B1")
    public double getCurrentPremiumsTransferred_PlanB1()
    {
        return currentPremiumsTransferred_PlanB1;
    }

    @Parameter (usageName="currentPremiumsTransferred_PlanB2", displayName="E4. Current premiums transferred - Plan B2")
    public double getCurrentPremiumsTransferred_PlanB2()
    {
        return currentPremiumsTransferred_PlanB2;
    }


//==============================================================================

//==============================================================================
// Methods:  "Analysis" methods to support simulation charts and graphs.
//==============================================================================

    public double analysis_DetermineTotalPremiumsReceived()
    {
        return (currentPremiumsReceived_PlanA1 +
                currentPremiumsReceived_PlanA2 +
                currentPremiumsReceived_PlanB1 +
                currentPremiumsReceived_PlanB2);
    }

    public double analysis_DetermineTotalAdvertisingExpenses()
    {
        return (currentAdvertisingExpenses_PlanA1 +
                currentAdvertisingExpenses_PlanA2 +
                currentAdvertisingExpenses_PlanB1 +
                currentAdvertisingExpenses_PlanB2);
    }

    public double analysis_DetermineTotalPremiumsTransferred()
    {
        return (currentPremiumsTransferred_PlanA1 +
                currentPremiumsTransferred_PlanA2 +
                currentPremiumsTransferred_PlanB1 +
                currentPremiumsTransferred_PlanB2);
    }

//==============================================================================



//==============================================================================
// Methods:  General methods for the agent.
//==============================================================================


//==============================================================================



//==============================================================================
// Methods:  getter and setter methods
//------------------------------------------------------------------------------



//==============================================================================

}//end Exchange class