/*****************************************************************************
 * © 2015 Avaya Inc. All rights reserved.
 ****************************************************************************/
package com.avaya.zephyr.services.sample_services.CallableService.menus;

import java.util.UUID;

import com.avaya.collaboration.call.Call;
import com.avaya.collaboration.call.media.DigitCollectorOperationCause;
import com.avaya.collaboration.call.media.MediaListenerAbstract;
import com.avaya.collaboration.call.media.PlayOperationCause;
import com.avaya.collaboration.call.media.RecordOperationCause;
import com.avaya.collaboration.util.logger.Logger;
import com.avaya.zephyr.services.sample_services.CallableService.PromptsToPlay;
import com.avaya.zephyr.services.sample_services.CallableService.attributeReaders.ServiceAttributeReaderImpl;
import com.avaya.zephyr.services.sample_services.CallableService.operations.PlayAnnouncementOperation;
import com.avaya.zephyr.services.sample_services.CallableService.operations.PlayAnnouncementOperationImpl;
import com.avaya.zephyr.services.sample_services.CallableService.operations.PromptAndCollectOperation;
import com.avaya.zephyr.services.sample_services.CallableService.operations.PromptAndCollectOperationImpl;
import com.avaya.zephyr.services.sample_services.CallableService.operations.RecordMessageOperation;
import com.avaya.zephyr.services.sample_services.CallableService.operations.RecordMessageOperationImpl;
import com.avaya.zephyr.services.sample_services.CallableService.util.CallableServiceHttpUtil;

public class CallableServiceMainMenuMediaListener extends MediaListenerAbstract
{
    private static final String RECORD = "1";
    private static final String PLAY_PREV_RECORDED = "2";
    private static final String DEL_PREV_RECORDED = "3";
    private static final String EXIT_APP = "*";
    private static final int HTTP_OK = 200;

    private final Call call;
    private final PlayAnnouncementOperation playAnnouncementOperation;
    private final PromptAndCollectOperation promptAndCollectOperation;
    private final RecordMessageOperation recordMessageOperation;
    private final Logger logger;

    public CallableServiceMainMenuMediaListener(final Call call)
    {
        this(call, Logger.getLogger(CallableServiceMainMenuMediaListener.class));
    }

    public CallableServiceMainMenuMediaListener(final Call call, final Logger logger)
    {
        this(call, new PlayAnnouncementOperationImpl(), new PromptAndCollectOperationImpl(),
                new RecordMessageOperationImpl(), logger);
    }

    CallableServiceMainMenuMediaListener(final Call call,
            final PlayAnnouncementOperation playAnnouncementOperation,
            final PromptAndCollectOperation promptAndCollectOperation,
            final RecordMessageOperation recordMessageOperation, final Logger logger)
    {
        this.call = call;
        this.playAnnouncementOperation = playAnnouncementOperation;
        this.promptAndCollectOperation = promptAndCollectOperation;
        this.recordMessageOperation = recordMessageOperation;
        this.logger = logger;
    }

    @Override
    public void digitsCollected(final UUID requestId, final String digits,
            final DigitCollectorOperationCause cause)
    {
        if (logger.isFinerEnabled())
        {
            logger.finer("CallableServiceMainMenuMediaListener digitsCollected ENTER with digit: " + digits +
                    ", requestId: " + requestId.toString() + ", cause: " + cause.name());
        }
        try
        {
            switch (digits)
            {
                case RECORD:
                    logger.info("CallableServiceMainMenuMediaListener digitsCollected: Request to record.");
                    setUpRecording();
                    break;
                case PLAY_PREV_RECORDED:
                    logger.info("CallableServiceMainMenuMediaListener digitsCollected: Request to play previous recorded message.");
                    playPrevRecorded(call);
                    break;
                case DEL_PREV_RECORDED:
                    logger.info("CallableServiceMainMenuMediaListener digitsCollected: Request to delete the previous recorded message.");
                    delPrevRecorded(call);
                    break;
                case EXIT_APP:
                    logger.info("CallableServiceMainMenuMediaListener digitsCollected: Request to exit.");
                    playThankYou(call);
                    break;
                default:
                    logger.error("CallableServiceMainMenuMediaListener digitsCollected: invalid digit=" +
                            digits);
                    playThankYou(call);
                    break;
            }
        }
        catch (final Exception e)
        {
            logger.error("CallableServiceMainMenuMediaListener digitsCollected: failed operation exception=",
                    e);
            call.drop();
        }
        logger.finer("CallableServiceMainMenuMediaListener digitsCollected EXIT ");
    }

    @Override
    public void playCompleted(final UUID requestId, final PlayOperationCause cause)
    {
        if (logger.isFinestEnabled())
        {
            logger.finest("allableServiceMainMenuMediaListener playCompleted with requestId: " +
                    requestId.toString() + ", cause: " + cause.name());
        }
        final Object nextPrompt = call.getAttribute("nextPrompt");
        switch ((PromptsToPlay) nextPrompt)
        {
            case MAINMENU:
                logger.finer("CallableServiceMainMenuMediaListener playCompleted nextPrompt is MAINMENU");
                promptAndCollectOperation.executePromptAndCollectOperation(call, PromptsToPlay.MAINMENU);
                break;
            case RECORD:
                logger.finer("CallableServiceMainMenuMediaListener playCompleted nextPrompt is RECORD");
                recordMessageOperation.executeRecordMessageOperation(call);
                break;
            case BEEP:
                logger.finer("CallableServiceMainMenuMediaListener playCompleted nextPrompt is BEEP");
                call.setAttribute("nextPrompt", PromptsToPlay.RECORD);
                logger.finer("CallableServiceMainMenuMediaListener playCompleted set nextprompt to RECORD");
                playAnnouncementOperation.executePlayAnnouncementOperation(call, PromptsToPlay.BEEP);
                break;
            case APPROVE_OR_DISCARD:
                logger.finer("CallableServiceMainMenuMediaListener playCompleted nextPrompt is APPROVE_OR_DISCARD");
                call.setAttribute("nextPrompt", PromptsToPlay.RECORDING_SAVED);
                logger.finer("CallableServiceMainMenuMediaListener playCompleted set nextprompt to RECORD_SAVED");
                promptAndCollectOperation.executePromptAndCollectOperation(call,
                        PromptsToPlay.APPROVE_OR_DISCARD);
                break;
            case RECORDING_SAVED:
                logger.finer("CallableServiceMainMenuMediaListener playCompleted nextPrompt is RECORDING_SAVED");
                break;
            case RETURN_TO_MAINMENU:
                logger.finer("CallableServiceMainMenuMediaListener playCompleted nextPrompt is RETURN_TO_MAINMENU");
                call.setAttribute("nextPrompt", PromptsToPlay.MAINMENU);
                logger.finer("CallableServiceMainMenuMediaListener.playCompleted set nextprompt to MAINMENU");
                promptAndCollectOperation.executePromptAndCollectOperation(call,
                        PromptsToPlay.RETURN_TO_MAINMENU);
                break;
            case THANKYOU:
                logger.finer("CallableServiceMainMenuMediaListener playCompleted nextPrompt is THANKYOU");
                call.drop();
                break;
            default:
                logger.error("CallableServiceMainMenuMediaListener playCompleted: invalid prompt=" +
                        (PromptsToPlay) nextPrompt);
                break;
        }
    }

    @Override
    public void recordCompleted(final UUID requestId, final RecordOperationCause cause)
    {
        logger.finer("CallableServiceMainMenuMediaListener recordCompleted ENTER.");

        if (logger.isFinestEnabled())
        {
            logger.finest("CallableServiceMainMenuMediaListener recordCompleted with requestId: " +
                    requestId.toString() + ", cause: " + cause.name());
        }
        call.setAttribute("nextPrompt", PromptsToPlay.RECORDING_SAVED);
        logger.finer("CallableServiceMainMenuMediaListener.recordCompleted set nextprompt to RECORD_SAVED");
        promptAndCollectOperation.executePromptAndCollectOperation(call, PromptsToPlay.APPROVE_OR_DISCARD);
        logger.finer("CallableServiceMainMenuMediaListener recordCompleted EXIT.");
    }

    protected void setUpRecording()
    {
        call.setAttribute("nextPrompt", PromptsToPlay.BEEP);
        logger.finer("CallableServiceMainMenuMediaListener setUpRecording set nextPrompt to BEEP");
        playAnnouncementOperation
                .executePlayAnnouncementOperation(call, PromptsToPlay.RECORD);
    }

    protected void playPrevRecorded(final Call call)
    {
        logger.finer("CallableServiceMainMenuMediaListener playPrevRecorded ENTER");
        try
        {
            final CallableServiceHttpUtil callableServiceHttpUtil = new CallableServiceHttpUtil();
            call.setAttribute("nextPrompt", PromptsToPlay.APPROVE_OR_DISCARD);
            logger.finer("CallableServiceMainMenuMediaListener playPrevRecorded set nextprompt to RECORD");
            final String fileName =
                    (new ServiceAttributeReaderImpl()).getFileName(call.getCalledParty()) + ".wav";

            if (callableServiceHttpUtil.requestPut(fileName).equals("EXISTS"))
            {
                logger.finest("CallableServiceMainMenuMediaListener playPrevRecorded previously recorded file exists ");
                playAnnouncementOperation.executePlayAnnouncementOperation(call, fileName);
            }
            else
            {
                logger.error("CallableServiceMainMenuMediaListener playPrevRecorded: Could not find the previously recorded file.");
                playThankYou(call);
            }
        }
        catch (final Exception exception)
        {
            logger.error("CallableServiceMainMenuMediaListener playPrevRecorded: exception=", exception);
            call.drop();
        }
        logger.finer("CallableServiceMainMenuMediaListener playPrevRecorded EXIT");
    }

    protected void delPrevRecorded(final Call call)
    {
        logger.finer("CallableServiceMainMenuMediaListener delPrevRecorder ENTER");
        try
        {
            final CallableServiceHttpUtil callableServiceHttpUtil = new CallableServiceHttpUtil();
            final String fileName =
                    (new ServiceAttributeReaderImpl()).getFileName(call.getCalledParty()) + ".wav";

            if (logger.isFinestEnabled())
            {
                logger.finest("CallableServiceMainMenuMediaListener delPrevRecorder fileName: " + fileName);
            }
            if (callableServiceHttpUtil.requestDelete(fileName) == HTTP_OK)
            {
                logger.finest("CallableServiceMainMenuMediaListener delPrevRecorder http request to delete recorded file successfully.");
                playThankYou(call);
            }
        }
        catch (final Exception serviceAttribute)
        {
            logger.error("CallableServiceMainMenuMediaListener delPrevRecorded: exception=", serviceAttribute);
            call.drop();
        }
        logger.finer("CallableServiceMainMenuMediaListener delPrevRecorder EXIT");
    }

    protected void playThankYou(final Call call)
    {
        logger.finest("CallableServiceMainMenuMediaListener playThankYou set nextPrompt to THANKYOU");
        call.setAttribute("nextPrompt", PromptsToPlay.THANKYOU);
        playAnnouncementOperation.executePlayAnnouncementOperation(call, PromptsToPlay.THANKYOU);
    }
}
