/*****************************************************************************
 * © 2014 Avaya Inc. All rights reserved.
 ****************************************************************************/
package com.avaya.services.Callingpolicies;

import com.avaya.collaboration.call.Call;
import com.avaya.collaboration.call.CallListenerAbstract;
import com.avaya.collaboration.call.CallTerminationCause;
import com.avaya.collaboration.call.Participant;
import com.avaya.collaboration.call.ParticipantFactory;
import com.avaya.collaboration.call.TheCallListener;
import com.avaya.collaboration.util.logger.Logger;

@TheCallListener
public final class CallingPoliciesCallListener extends CallListenerAbstract
{
    private final PromptAndCollectOperation promptAndCollectOperation;
    private final Logger logger;

    public CallingPoliciesCallListener()
    {
        this(new PromptAndCollectOperationImpl(), Logger.getLogger(CallingPoliciesCallListener.class));
    }

    CallingPoliciesCallListener(final PromptAndCollectOperation promptAndCollectOperation, final Logger logger)
    {
        this.promptAndCollectOperation = promptAndCollectOperation;
        this.logger = logger;
    }

    @Override
    public void callIntercepted(final Call call)
    {
        logger.finer("callIntercepted ENTER");
        promptAndCollectOperation.executePromptAndCollectOperation(call);
        logger.finer("callIntercepted EXIT");
    }

    @Override
    public void callAnswered(final Call call)
    {
        logger.finer("callAnswered ENTER");
        promptAndCollectOperation.cancelSequentialForkingTimer(call);
        logger.finer("callAnswered EXIT");
    }

    @Override
    public void callAlerting(final Participant alertingParty)
    {
        logger.finer("callAlerting ENTER");
        final Call call = alertingParty.getCall();
        if (CallingPoliciesMediaListener.SEQUENTIALFORK_DIGIT5.equals(CallingPoliciesMediaListener.callDigitSelectMap.get(call.getId())))
        {
            // make sure that noAnswerTimer is started at most once per call.
            if (CallingPoliciesMediaListener.NO.equals((String) call.getAttribute(CallingPoliciesMediaListener.NOANSWERTIMER_ENABLED)))
            {
                logger.finer("callAlerting EXIT - noAnswerTimer had already been started for this call.");
                return;
            }
            promptAndCollectOperation.startNoAnswerTimer(call);
            call.setAttribute(CallingPoliciesMediaListener.NOANSWERTIMER_ENABLED, CallingPoliciesMediaListener.NO);
        }
        logger.finer("callAlerting EXIT");
    }

    @Override
    public void participantDropped(final Call call, final Participant droppedParticipant, final CallTerminationCause cause)
    {
        logger.finer("participantDropped ENTER");
        if (call.getActiveParties().isEmpty())
        {
            logger.finer("participantDropped EXIT - Last participant dropped.");
            return;
        }
        final String optionChosen = CallingPoliciesMediaListener.callDigitSelectMap.get(call.getId());
        if (CallingPoliciesMediaListener.NO_SELECTION.equals(optionChosen))
        {
            // optionChosen was cleared in cancelSequentialForkingTimer() for Sequential Forking option
            // in order to prevent adding new party
            logger.finer("participantDropped EXIT - optionChosen is empty");
            return;
        }
        logger.finest("participantDropped - optionChosen is: " + optionChosen);
        if (CallingPoliciesMediaListener.CALLBACK_DIGIT7.equals(optionChosen))
        {
            // Serial Calling Call Back option
            // If caller dropped the call, call it back
            if (call.getCallingParty().equals(droppedParticipant))
            {
                try
                {
                    call.addParticipant(ParticipantFactory.create(droppedParticipant.getHandle(), droppedParticipant.getDomain(),
                            droppedParticipant.getDisplayName()));
                }
                catch (final IllegalArgumentException e)
                {
                    logger.finest("participantDropped - existing participant cannot be reused.");
                    call.drop();
                }
            }
        }
        else if ((CallingPoliciesMediaListener.MAKEANOTHERCALL_DIGIT6.equals(optionChosen) ||
                CallingPoliciesMediaListener.SEQUENTIALFORK_DIGIT5.equals(optionChosen)) &&
                !call.getCallingParty().equals(droppedParticipant)) // i.e. the alerting or answering party is dropped.
        {
            // Serial Calling Make Another Call or Sequential Forking options
            // If called party is dropped, make a new call to redirectingNumber
            promptAndCollectOperation.addPartyToCall(call);
        }
        CallingPoliciesMediaListener.callDigitSelectMap.remove(call.getId());

        logger.finer("participantDropped EXIT");
    }

    @Override
    public void callTerminated(final Call call, final CallTerminationCause cause)
    {
        logger.finer("callTerminated ENTER");
        promptAndCollectOperation.cancelSequentialForkingTimer(call);
        logger.finer("callTerminated ENTER");
    }
}
