package apz.pirichat.server;
import java.io.IOException;
import java.net.Socket;
import apz.pirichat.shared.PiriConstants;
import apz.pirichat.shared.PiriNotConnectedException;
/*
    Connection.java

    This class holds all information about a connection, including pointers
    to the two threads, as well as authentication information about the
    client

*/

public class Connection
{
    // Variables specific to the connection
    private String mUserName;
    private PiriConstants.Status mStatus;
    private ClientRecvThread clientRecvThread;

    public Connection(Socket pSocket)
    {
        setStatus(PiriConstants.Status.STATUS_OFFLINE);
        // Create & run client thread
        clientRecvThread = new ClientRecvThread(this, pSocket);
        clientRecvThread.start();
    }

    public boolean isConnected()
    {
        return clientRecvThread.getSocket().isConnected();
    }

    public boolean isAuthenticated() throws PiriNotConnectedException
    {
        if (isConnected() == false)
            throw new PiriNotConnectedException();
        return (mUserName != null);
    }

    public String getUserName() throws PiriNotConnectedException
    {
        if (isConnected() == false)
            throw new PiriNotConnectedException();
        return mUserName;
    }

    public void setUserName(String pUserName)
    {
        mUserName = pUserName;
    }

    public PiriConstants.Status getStatus()
    {
        return mStatus;
    }

    public void setStatus(PiriConstants.Status pStatus)
    {
        mStatus = pStatus;
    }

    public void disconnect()
    {
        // Close the current socket
        try{ clientRecvThread.getSocket().getSocket().close(); }
        catch(Exception e) { PiriServer.fatalError(e); };
        // Reset connection values
        setUserName(null);
        setStatus(PiriConstants.Status.STATUS_OFFLINE);
        // Stop thread
        clientRecvThread.stop();
    }


    public void sendOK(Command pOriginal) throws PiriNotConnectedException
    {
      // This command sends an affirmative when no other info is needed
      // Opposite of sendError

    }

    public void sendError(Command pOriginal, String pErrCode, String pErrMessage) throws PiriNotConnectedException
    {
        // We call this is if we want to send an error message to the client...
        if (isConnected() == false)
            throw new PiriNotConnectedException();
        // Create and initialise our error object
        Command reply = new Command("error", null);
        reply.setParameter("errCmd", pOriginal.getCommand());
        reply.setParameter("errCode", pErrCode);
        reply.setParameter("errMessage", pErrMessage);
        // Send it...
        sendReply(pOriginal, reply);
    }

    public void sendReply(Command pOriginal, Command pReply) throws PiriNotConnectedException
    {
        // We use this if we want to send a reply to a previous command
        pReply.setParameter("originalCmd", pOriginal.getCommand());
        // Send it...
        sendMessage(pReply);
    }

    public void sendMessage(Command pCommand) throws PiriNotConnectedException
    {
        // Check whether we are online / not
        if (isConnected() == false)
            throw new PiriNotConnectedException();
        // Otherwise, attempt to send
        try
        {
            clientRecvThread.getSocket().sendMessage(pCommand);
        }
        // Error handling...
        catch(PiriNotConnectedException e)
        {
            throw(e);
        }
        catch(IOException e)
        {
            PiriServer.fatalError(e);
        }
    }
}
