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

    Copyright (C) 2009-2011 by Frederic-Charles Barthelery,
                               Nikita Kozlov,
                               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://www.beem-project.com/

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

import net.java.otr4j.OtrEngineHost;
import net.java.otr4j.OtrEngineListener;
import net.java.otr4j.OtrException;
import net.java.otr4j.session.Session;
import net.java.otr4j.session.SessionID;
import net.java.otr4j.session.SessionImpl;
import net.java.otr4j.session.SessionStatus;

import java.security.PublicKey;
import java.util.Hashtable;
import java.util.Map;

/**
 * This class handle the OTR behavior.
 */
public class OtrEngine {

    private OtrEngineHost host;
    private Map<SessionID, Session> sessions;
    private final OtrEngineListener listener;

    /**
     * Create an OtrEngine.
     *
     * @param host the host part of the OTR engine
     * @param listener the listener for OTR events
     */
    public OtrEngine(OtrEngineHost host, OtrEngineListener listener) {
	this.host = host;
	this.listener = listener;
    }

    /**
     * Get the OTR session.
     *
     * @param sessionID the session id
     * @return the OTR session
     */
    private Session getSession(SessionID sessionID) {

	if (sessionID == null || sessionID.equals(SessionID.Empty))
	    throw new IllegalArgumentException();

	if (sessions == null)
	    sessions = new Hashtable<SessionID, Session>();

	if (!sessions.containsKey(sessionID)) {
	    Session session = new SessionImpl(sessionID, host);
	    sessions.put(sessionID, session);

	    session.addOtrEngineListener(listener);
	    return session;
	} else
	    return sessions.get(sessionID);
    }

    /**
     * Get the status of an OTR session.
     *
     * @param sessionID the session id
     * @return the status
     */
    public SessionStatus getSessionStatus(SessionID sessionID) {
	return this.getSession(sessionID).getSessionStatus();
    }

    /**
     * Transform a message received in an OTR session.
     *
     * @param sessionID the session id
     * @param msgText the encrypted message received
     * @return the decrypted message
     * @throws OtrException if an error occurs
     */
    public String transformReceiving(SessionID sessionID, String msgText)
	throws OtrException {
	return this.getSession(sessionID).transformReceiving(msgText);
    }

    /**
     * Transform a message to be sent in an OTR session.
     *
     * @param sessionID the session id
     * @param msgText the clear message to send
     * @return the encrypted message
     * @throws OtrException if an error occurs
     */
    public String[] transformSending(SessionID sessionID, String msgText)
	throws OtrException {
	return this.getSession(sessionID).transformSending(msgText, null);
    }

    /**
     * End an OTR session.
     *
     * @param sessionID the session id
     * @throws OtrException if an error occurs
     */
    public void endSession(SessionID sessionID) throws OtrException {
	this.getSession(sessionID).endSession();
    }

    /**
     * Start an OTR session.
     *
     * @param sessionID the session id
     * @throws OtrException if an error occurs
     */
    public void startSession(SessionID sessionID) throws OtrException {
	this.getSession(sessionID).startSession();
    }

    /**
     * Refresh an OTR session.
     *
     * @param sessionID the session id
     * @throws OtrException if an error occurs
     */
    public void refreshSession(SessionID sessionID) throws OtrException {
	this.getSession(sessionID).refreshSession();
    }

    /**
     * Get the remote public key of an OTR session.
     *
     * @param sessionID the session id
     * @return the public key of the remote peer
     */
    public PublicKey getRemotePublicKey(SessionID sessionID) {
	return this.getSession(sessionID).getRemotePublicKey();
    }

}
