package org.vtlabs.firsttelcoproject.session;

import javax.servlet.sip.SipServletRequest;
import javax.servlet.sip.SipServletResponse;
import javax.servlet.sip.SipSession;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Observer;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.log.Log;
import org.mobicents.mscontrol.MsConnection;
import org.mobicents.mscontrol.MsConnectionEvent;
import org.mobicents.mscontrol.MsLinkEvent;
import org.mobicents.mscontrol.MsLinkMode;
import org.mobicents.servlet.sip.seam.entrypoint.media.MediaController;
import org.mobicents.servlet.sip.seam.media.framework.IVRHelper;
import org.mobicents.servlet.sip.seam.media.framework.MediaSessionStore;

@Name("firstTelcoClass")
@Scope(ScopeType.STATELESS)

public class FirstTelcoClass {
    @In MediaController mediaController;
    @In MediaSessionStore mediaSessionStore;
    @In IVRHelper ivrHelper;
    @In SipSession sipSession;
    
    @In(required=false,scope=ScopeType.SESSION) 
    @Out(required=false,scope=ScopeType.SESSION) 
    String mode;
    
    @Logger 
    private static Log log;
    
    /* [0]
     * Recebe a chamada através da request INVITE, algum SIP phone enviou
     * uma chamada para nossa aplicacao.
     */
    @Observer("INVITE")
    public void doInvite(SipServletRequest request) throws Exception {
        /* [1]
         *  Vamos armazenar a request INVITE na sessao, pois
         *  podemos necessitar dela no futuro. 
         */
        sipSession.setAttribute("inviteRequest", request);
        
        /* [2]
         * Vamos enviar uma resposta provisional para o SIP phone
         * que chamou nossa aplicacao, esta resposta sera o 180 Ringing
         * isto fara com o que o SIP phone comece a tocar.
         */
        request.createResponse(180).send();
        
        /* [3]
         * Vamos pegar o SDP do SIP phone que esta no body do INVITE
         */
        String sdp = new String((byte[]) request.getContent());
        
        /* [4]
         * Agora vamos criar uma conexao entre o SIP phone chamador o um recurso
         * de packet relay dentro do Mobicents, veja que o SDP do chamador é 
         * passado na chamada do metodo.
         */
        mediaController.createConnection("media/trunk/PacketRelay/$").modify("$", sdp);
    }
    
    /* [5]
     * Uma vez que a conexão RTP esta totalmente negociada, ou seja o nosso recurso de
     * packet relay já sabe como se receber e enviar RTP para o chamador, este callback
     * e disparado.
     */
    @Observer("connectionOpen")
    public void connectionOpenRequest(MsConnectionEvent event) throws Exception {
        /* [6]
         * Neste momento precisamos resgatar a MsConnection objeto que representa
         * a conexão RTP entre o recurso de packet relay, e o SIP phone chamador.
         */
        MsConnection connection = mediaSessionStore.getMsConnection();

        /* [7]
         * Agora precisamos resgatar o SDP gerado pelo recurso packet relay, pois
         * precisaremos informar o SIP phone chamador qual e o SDP do media server.
         */
        String sdp = event.getConnection().getLocalDescriptor();
        
        /* [8]
         * Resgatamos o INVITE atraves da sessao
         */
        SipServletRequest inviteRequest = (SipServletRequest) 
            sipSession.getAttribute("inviteRequest");
        
        /* [9]
         * Vamos criar a resposta 200 OK para podermos enviar posteriormente
         * ao chamador. 
         */
        SipServletResponse sipServletResponse = inviteRequest
                .createResponse(SipServletResponse.SC_OK);

        /* [10]
         * Precisamos adicionar a resposta 200 OK o SDP do recurso de packet relay,
         * obtido no passo [7], e enviar a mesma para o SIP phone, neste momento
         * o SIP phone chamador sinalizará que a chamada foi atendida.
         */
        sipServletResponse.setContent(sdp, "application/sdp");
            sipServletResponse.send();
        
        /* [11]
         * Agora precisamos conectar o recurso packet realy, com um recurso de IVR
         * (recurso que nos permite executar operacoes de reproducao, e gravacao de
         * audio, e recepcao de digitos DTMF)
        */  
        mediaController.createLink(MsLinkMode.FULL_DUPLEX)
            .join("media/trunk/IVR/$",
                    connection.getEndpoint().getLocalName());
    }
    
    /* [12]
     * Quando o link entre o recurso packet relay e o IVR solicitado no passo [12]
     * for estabelecido, este callback sera disparado, representando que estamos
     * com uma chamada SIP estabelecida entre um SIP phone e um recurso de IVR 
     * de nosso media server, ou seja agora e hora de comecar a brincadeira.
     */
    @Observer("linkConnected")
    public void doLinkConnected(MsLinkEvent event) {
        log.info("Executando play da mensagem de bemvindo");

    	/* [13]
         * Executa o comando play que reproduzirá uma mensagem de bem vindo.
         */
        ivrHelper.playAnnouncementWithDtmf("http://dl.dropbox.com/u/2134454/ensinar-mobicents-post/bemvindo.wav");
    }
    
    /* [14]
     * Este callback sera chamado sempre que um digito DTMF for recebido pelo
     * nosso media server.
     */
    @Observer("DTMF")
    public void doDtmf(String digit) throws Exception{
        log.info("DTMF digitos recebidos " + digit);
        
        for(char dig : digit.toCharArray()){
        	String file = "http://dl.dropbox.com/u/2134454/ensinar-mobicents-post/" + dig +".wav";
            log.info("Executando play do arquivo: " + file);

        	/* [15]
             * Executa o play de cada digito recebido.
             */
            ivrHelper.playAnnouncementWithDtmf(file);
        }
    }

    /* 
     * Quando o SIP phone desligar a chamada este Callback sera disparado
     * precisamos apenas responder com um 200 OK para que a chamada seja 
     * desligada.
     */
    @Observer("BYE")
    public void doBye(SipServletRequest request) throws Exception {
        request.createResponse(200).send();
    }
    
    @Observer("announcementComplete")
    public void doAnnouncementeComplet(){
        log.info("Play finalizado!");
    }

    
}

