/*
    BEEM is a videoconference application on the Android Platform.

    Copyright (C) 2009 by Frederic-Charles Barthelery,
                          Jean-Manuel Da Silva,
                          Nikita Kozlov,
                          Philippe Lago,
                          Jean Baptiste Vergely,
                          Vincent Veronis.

    This file is part of BEEM.

    BEEM is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    BEEM is distributed 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.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with BEEM.  If not, see <http://www.gnu.org/licenses/>.

    Please send bug reports with examples or suggestions to
    contact@beem-project.com or http://dev.beem-project.com/

    Epitech, hereby disclaims all copyright interest in the program "Beem"
    written by Frederic-Charles Barthelery,
               Jean-Manuel Da Silva,
               Nikita Kozlov,
               Philippe Lago,
               Jean Baptiste Vergely,
               Vincent Veronis.

    Nicolas Sadirac, November 26, 2009
    President of Epitech.

    Flavien Astraud, November 26, 2009
    Head of the EIP Laboratory.

*/
package com.beem.project.beem.jingle;

import java.util.ArrayList;
import java.util.List;

import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.jingle.JingleManager;
import org.jivesoftware.smackx.jingle.JingleSession;
import org.jivesoftware.smackx.jingle.JingleSessionRequest;
import org.jivesoftware.smackx.jingle.listeners.JingleSessionListener;
import org.jivesoftware.smackx.jingle.listeners.JingleSessionRequestListener;
import org.jivesoftware.smackx.jingle.media.JingleMediaManager;
import org.jivesoftware.smackx.jingle.media.PayloadType;
import org.jivesoftware.smackx.jingle.nat.BasicTransportManager;
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
import org.sipdroid.media.codecs.CodecManager;

import android.content.Context;
import android.util.Log;
import android.content.Intent;

import com.beem.project.beem.ui.CallScreen;

// TODO: Auto-generated Javadoc
/**
 * Beem Jingle Service, manage jingle call.
 * @author nikita
 */
public class JingleService {
	private static final String TAG = "JingleService";
	private JingleManager mJingleManager;
	private final List<JingleMediaManager> mMediaManagers;
	private JingleSession mIn;
	private JingleSession mOut;
	private Context mContext;

	/**
	 * JingleService constructor.
	 * @param xmppConnection a valid XMPPConnection
	 */
	public JingleService(final XMPPConnection xmppConnection,final Context ctx) {
		BasicTransportManager bt = new BasicTransportManager();
		mMediaManagers = new ArrayList<JingleMediaManager>();
		mMediaManagers.add(new MicrophoneRTPManager(bt, ctx));
		CodecManager.load();
		mContext = ctx;
	}

	/**
	 * finish to construct the instance.
	 * @param conn the xmppConnection used with constructor
	 */
	public void initWhenConntected(XMPPConnection conn) {
		mJingleManager = new JingleManager(conn, mMediaManagers);
		mJingleManager.addJingleSessionRequestListener(new BeemJingleSessionRequestListener());
	}

	/**
	 * begin a jingle call.
	 * @param receiver the call receiver
	 */
	public void call(final String receiver) {
		try {
			mOut = mJingleManager.createOutgoingJingleSession(receiver);
			// TODO configure out avec addMediaSession et addNegociator
			mOut.addListener(new BeemJingleCallerSessionListener());
			mOut.startOutgoing();
		} catch (XMPPException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/*private void call(PayloadType pt, TransportCandidate remoteCandidate,
			TransportCandidate localCandidate, JingleSession jingleSession) {

		audio = new JAudioLauncher(localCandidate.getPort(), remoteCandidate.getIp(),
				remoteCandidate.getPort(), pt); 

	}*/

	/**
	 * Listen on receiver session events.
	 * @author nikita
	 */
	private class BeemJingleReceiverSessionListener implements JingleSessionListener {

		/**
		 * constructor.
		 */
		public BeemJingleReceiverSessionListener() {
			super();
			// TODO Auto-generated constructor stub
		}

		@Override
		public void sessionClosed(String reason, JingleSession jingleSession) {
			System.out.println("Session " + jingleSession.getResponder() + "closedd because " + reason);
			//audio.stopMedia();

		}

		@Override
		public void sessionClosedOnError(XMPPException e, JingleSession jingleSession) {
			// TODO Auto-generated method stub
			System.out.println("Session " + jingleSession.getResponder() + " closed");
			//audio.stopMedia();
		}

		@Override
		public void sessionDeclined(String reason, JingleSession jingleSession) {
			Log.d(TAG, "Session " + jingleSession.getResponder() + "declined because " + reason);
		}

		@Override
		public void sessionEstablished(PayloadType pt, TransportCandidate remoteCandidate,
				TransportCandidate localCandidate, JingleSession jingleSession) {
			Log.d(TAG, "Session " + jingleSession.getResponder() + "established");
			jingleSession.getSession().getMediaSession(pt.getName());
		}

		@Override
		public void sessionMediaReceived(JingleSession jingleSession, String participant) {
			Log.d(TAG, "Session Media received from " + participant);
		}

		@Override
		public void sessionRedirected(String redirection, JingleSession jingleSession) {
		}
	}

	/**
	 * Listen on caller session events.
	 * @author nikita
	 */
	private class BeemJingleCallerSessionListener implements JingleSessionListener {

		private static final int SLP_DURATION = 20000;

		/**
		 * constructor.
		 */
		public BeemJingleCallerSessionListener() {
			super();
			// TODO Auto-generated constructor stub
		}

		@Override
		public void sessionClosed(final String reason, final JingleSession jingleSession) {
			System.out.println("Session " + jingleSession.getResponder() + "closed because " + reason);
		}

		@Override
		public void sessionClosedOnError(final XMPPException e, final JingleSession jingleSession) {
			System.out.println("Session " + jingleSession.getResponder() + " closed on error");
		}

		@Override
		public void sessionDeclined(final String reason, final JingleSession jingleSession) {
			Log.d(TAG, "Session " + jingleSession.getResponder() + "declined because " + reason);
		}

		@Override
		public void sessionEstablished(final PayloadType pt, final TransportCandidate remoteCandidate,
				final TransportCandidate localCandidate, final JingleSession jingleSession) {
			Log.d(TAG, "Session " + jingleSession.getResponder() + "established");
			Intent callIntent = new Intent(mContext, CallScreen.class);
			callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			mContext.startActivity(callIntent);
			//call(pt, remoteCandidate, localCandidate, jingleSession);
		}

		@Override
		public void sessionMediaReceived(final JingleSession jingleSession, final String participant) {
			// TODO Auto-generated method stub
			System.out.println("Session Media received from " + participant);
		}

		@Override
		public void sessionRedirected(final String redirection, final JingleSession jingleSession) {
			// TODO Auto-generated method stub
		}
	}

	/**
	 * Listen for a Jingle session request.
	 * @author nikita
	 */
	private class BeemJingleSessionRequestListener implements JingleSessionRequestListener {

		/**
		 * Constructor.
		 */
		public BeemJingleSessionRequestListener() {
			super();
		}

		@Override
		public void sessionRequested(JingleSessionRequest request) {
			System.out.println("Jingle Session request from " + request.getFrom());
			try {
				mIn = request.accept();
				mIn.addListener(new BeemJingleReceiverSessionListener());
				mIn.startIncoming();
			} catch (XMPPException e) {
				e.printStackTrace();
			}
		}
	}

}
