/*****************************************************************************
 * © 2017 Avaya Inc. All rights reserved.
 ****************************************************************************/
package com.avaya.services.CallDeflection;

import java.net.URISyntaxException;

import org.apache.commons.lang3.StringUtils;

import com.avaya.collaboration.businessdata.api.NoAttributeFoundException;
import com.avaya.collaboration.businessdata.api.ServiceNotFoundException;
import com.avaya.collaboration.call.Call;
import com.avaya.collaboration.call.Participant;
import com.avaya.collaboration.call.media.DigitOptions;
import com.avaya.collaboration.call.media.MediaFactory;
import com.avaya.collaboration.call.media.MediaService;
import com.avaya.collaboration.call.media.PlayItem;
import com.avaya.collaboration.util.logger.Logger;
import com.avaya.services.CallDeflection.util.ServiceAttributeReader;
import com.avaya.services.CallDeflection.util.ServiceAttributeReaderImpl;
import com.avaya.services.CallDeflection.util.TrafficInterfaceAddressRetriever;
import com.avaya.services.CallDeflection.util.TrafficInterfaceAddressRetrieverImpl;

public final class CallDeflectionMediaOperationsImpl implements CallDeflectionMediaOperations
{
    private final ServiceAttributeReader serviceAttributeReader;
    private final TrafficInterfaceAddressRetriever trafficInterfaceAddressRetriever;
    private final Logger logger;
    private int promptNumber = CallDeflectionMediaListener.PROMPT1;

    public CallDeflectionMediaOperationsImpl()
    {
        this(new ServiceAttributeReaderImpl(), new TrafficInterfaceAddressRetrieverImpl(),
                Logger.getLogger(CallDeflectionMediaOperationsImpl.class));
    }

    CallDeflectionMediaOperationsImpl(final ServiceAttributeReader serviceAttributeReader,
            final TrafficInterfaceAddressRetriever trafficInterfaceAddressRetriever,
            final Logger logger)
    {
        this.serviceAttributeReader = serviceAttributeReader;
        this.trafficInterfaceAddressRetriever = trafficInterfaceAddressRetriever;
        this.logger = logger;
    }

    /**
     * Prompt the caller to enter a digit to determine the call behaviour. First, we will use DigitOptions to indicate that we want to
     * collect 1 digit. Then, we will use PlayItem to specify the announcement we will use for the prompt.
     */
    @Override
    public void executePromptAndCollectOperation(final Call call, final int prompt)
    {

        logger.finer("executePromptAndCollectOperation ENTER");
        this.promptNumber = prompt;
        try
        {
            final DigitOptions digitOptions = MediaFactory.createDigitOptions();
            digitOptions.setNumberOfDigits(1);
            digitOptions.setTerminationKey("#");
            digitOptions.setTimeout(DigitOptions.DEFAULT_TIMEOUT_MILLISECONDS);

            final PlayItem playItem = setPlaySource(prompt);

            if (logger.isFinestEnabled())
            {
                logger.finest("executePromptAndCollectOperation: call=" + call + "; prompt and collect=" +
                        playItem + "; digit options=" + digitOptions);
            }

            final MediaService mediaService = MediaFactory.createMediaService();
            final Participant participant = call.getCallingParty();
            final CallDeflectionMediaListener callingDeflectionMediaListener = new CallDeflectionMediaListener(call, this);
            mediaService.promptAndCollect(participant, playItem, digitOptions, callingDeflectionMediaListener);
        }
        catch (final Exception e)
        {
            logger.warn("executePromptAndCollectOperation: exception=" + e);
            call.drop();
        }
    }

    @Override
    public void executePlayOperation(final Call call, final int prompt)
    {

        logger.finer("executePlayOperation ENTER");
        try
        {
            final PlayItem playItem = setPlaySource(prompt);

            if (logger.isFinestEnabled())
            {
                logger.finest("executePlayOperation: prompt=" + prompt + " call=" + call + "; play=" + playItem);
            }
            this.promptNumber = prompt;
            final MediaService mediaService = MediaFactory.createMediaService();
            final Participant participant = call.getCallingParty();
            final CallDeflectionMediaListener callingDeflectionMediaListener = new CallDeflectionMediaListener(call, this);
            mediaService.play(participant, playItem, callingDeflectionMediaListener);
        }
        catch (final Exception e)
        {
            logger.warn("executePlayOperation: exception=" + e);
            call.drop();
        }
    }

    private PlayItem setPlaySource(final int prompt) throws NoAttributeFoundException, ServiceNotFoundException, URISyntaxException
    {
        final PlayItem playItem = MediaFactory.createPlayItem();
        playItem.setInterruptible(true);
        playItem.setIterateCount(1);

        String sourcePath = serviceAttributeReader.getAnnouncementSourcePath();
        if (StringUtils.isBlank(sourcePath))
        {
            final String announcementFileNetworkProtocol = "https";// clusterAttributeReader.getAnnouncementFileNetworkProtocol();
            final String trafficInterfaceAddress = trafficInterfaceAddressRetriever.getTrafficInterfaceAddress();
            sourcePath =
                    announcementFileNetworkProtocol + "://" + trafficInterfaceAddress + "/services/CallDeflection/";
        }
        final String source = sourcePath + "/Prompt" + prompt + ".wav";
        playItem.setSource(source);
        return playItem;
    }

    @Override
    public int getPromptNumber()
    {
        return promptNumber;
    }
}
