package apz.pirichat.server;
import java.io.IOException;
import java.net.Socket;
import apz.pirichat.shared.ChatMessage;
import apz.pirichat.shared.PiriNotConnectedException;
import apz.pirichat.shared.PiriIDInUseException;

public class PiriServerData
{
    private Users mUsers = new Users();
    private Connections mConnection = new Connections();

//    private Rooms mRooms;

    public void PiriServerData()
    {
        mUsers = new Users();
//        mRooms = new Rooms();

    try{
mUsers.createUser("alanp", "Password");
    }
    catch(Exception e){;}



    }

    public void createConnection(Socket pSocket)
    {
        mConnection.createConnection(pSocket);
    }

    public void dataRecieved(Connection pConnection, Command pCommand)
    {
        try
        {
        // See what type of message this is by looking at destination field
        // If destination begins with ! - it's a command
        // If destination begins with # - it's a channel message
        // If destination begins with % it's to a user
//        String destination = pCommand.getDestination();
//        if (destination.startsWith("!"))
            processCommand(pConnection, pCommand);
//        if (destination.startsWith("#"))
//            sendChannelMessage(pConnection, pCommand);
//        if (destination.startsWith("%"))
//            sendUserMessage(pConnection, pCommand);
        }
        catch(Exception e) {;}
    }

    private void processCommand(Connection pConnection, Command pCommand) throws PiriNotConnectedException, IOException
    {
        // See which command to run
        String command = pCommand.getCommand();
        if (command.equals("disconnect"))
            cmdDisconnect(pConnection, pCommand);
        if (command.equals("init"))
            cmdInitialise(pConnection, pCommand);
        if (command.equals("register"))
            cmdRegister(pConnection, pCommand);
        if (command.equals("login"))
            cmdLogin(pConnection, pCommand);
        if (command.equals("status"))
            cmdStatus(pConnection, pCommand);
        if (command.equals("listUsers"))
            cmdStatus(pConnection, pCommand);
    }

    private void cmdDisconnect(Connection pConnection, Command pCommand)
    {
        // This is called by theclient, diconnects the current connection
        pConnection.disconnect();
    }

    private void cmdInitialise(Connection pConnection, Command pCommand) throws PiriNotConnectedException
    {
        // This is called by the client on initialisation
        // It returns basic server information (welcome mesage etc)
        // Attributes used: None!
        Command reply = new Command("init", null);
        reply.setParameter("welcome", "Welcome to PiriChat v1.0");
        reply.setParameter("serverName", "Alan's Server");
        reply.setParameter("admin", "alan@alancode.net");
        pConnection.sendReply(pCommand, reply);
    }

    private void cmdRegister(Connection pConnection, Command pCommand) throws PiriNotConnectedException
    {
        // This the command used to create a new account
        // Attributes required:
        //  userName - Desired username
        //  password - Password
        // Optional attributes:
        //  displayName - Nickname
        //  contactAddress - E-mail address
        //  websiteUrl - URL to website
        // Check the REQUIRED attributes are present
        if (pCommand.doesParameterExist("userName") == false)
        {
            pConnection.sendError(pCommand, "userNameMissing", "User name attribute not supplied");
            return;
        }
        if (pCommand.doesParameterExist("password") == false)
        {
            pConnection.sendError(pCommand, "passwordMissing", "Password attribute not supplied");
            return;
        }
        String userName = pCommand.getParameter("userName");
        String password = pCommand.getParameter("password");
        // Check username is not zero length, is less than 250 chars and doesn't begin with !, and is un-reserved
        if (userName.length() == 0)
        {
            pConnection.sendError(pCommand, "userNameZeroLength", "User name attribute is zero-length");
            return;
        }
        if (userName.length() >= 250)
        {
            pConnection.sendError(pCommand, "userNameTooLong", "User name attribute is longer than maximum length");
            return;
        }
        if (userName.startsWith("!"))
        {
            pConnection.sendError(pCommand, "userNameProtected", "User name attribute starts with a protected symbol");
            return;
        }
        if (mUsers.doesUserExist(userName))
        {
            pConnection.sendError(pCommand, "userNameReserved", "User name attribute is already reserved");
            return;
        }
        // Everything is ok... create our user object
        // Set optional attributes if they are present
        try
        {
            // Create user object
            User user = mUsers.createUser(userName, password);
            if (pCommand.doesParameterExist("displayName"))
                user.setContactAddress(pCommand.getParameter("displayName"));
            if (pCommand.doesParameterExist("contactAddress"))
                user.setContactAddress(pCommand.getParameter("contactAddress"));
            if (pCommand.doesParameterExist("websiteUrl"))
                user.setContactAddress(pCommand.getParameter("websiteUrl"));
            // Tell user registration completed
            pConnection.sendOK(pCommand);
        }
        catch(PiriNotConnectedException e)
        {
            throw(e);
        }
        catch(PiriIDInUseException e)
        {
            PiriServer.fatalError(e);
        }
    }

    private void cmdLogin(Connection pConnection, Command pCommand) throws PiriNotConnectedException
    {
        // This is called by client to request login
        // Attributes used: userName, password
        //  Username of client, password - Password protecting account
        // Check parameters exist
        if (pCommand.doesParameterExist("userName") == false)
        {
            pConnection.sendError(pCommand, "userNameMissing", "User name attribute not supplied");
            return;
        }
        if (pCommand.doesParameterExist("password") == false)
        {
            pConnection.sendError(pCommand, "passwordNotMissing", "Password attribute not supplied");
            return;
        }
        // Read attribute values
        String userName = pCommand.getParameter("userName");
        String password = pCommand.getParameter("password");
        // Check username exists
        if (mUsers.doesUserExist(userName) == false)
        {
            pConnection.sendError(pCommand, "userNameNotFound", "User name not found");
            return;
        }
        // User exists ok.. so obtain a reference to our user name
        User user = mUsers.getUser(userName);
        // Check password, if not throw error
        if (user.checkPassword(password) == false)
        {
            pConnection.sendError(pCommand, "passwordIncorrect", "Incorrect password");
            return;
        }
        // If we arrived here everything is OK
        pConnection.setUserName(userName);
        pConnection.setStatus(Connection.Status.STATUS_ONLINE);
        // Send success message
        pConnection.sendOK(pCommand);
    }

    private void cmdStatus(Connection pConnection, Command pCommand) throws PiriNotConnectedException
    {
        // This command returns basic status information about client/server
        Command reply = new Command("status", null);
        reply.setParameter("welcome", "Welcome to PiriChat v1.0");
        reply.setParameter("serverName", "Alan's Server");
        reply.setParameter("admin", "alan@alancode.net");
        reply.setParameter("userName", pConnection.getUserName());
        reply.setParameter("displayName", mUsers.getUser(pConnection.getUserName()).getDisplayName());
        reply.setParameter("group", String.valueOf(mUsers.getUser(pConnection.getUserName()).getGroup()));
        pConnection.sendReply(pCommand, reply);
    }

    private void cmdEnumerateUsers(Connection pConnection, Command pCommand) throws PiriNotConnectedException
    {


        // This command returns a list of all the  users
        // Attributes:
        //  showBusy - If set, will list users with status set to 'busy'
        //  showOffline - If set, will show offline users
        //  showHidden - If set, will show users with hidden flag
        //                  note, this requires mod or admin access!
        //  Defaults to visibile online normal users

//        Users[] users = mUsers.getUsers();


    }

    private void cmdGetUserProperties(Connection pConnection, Command pCommand) throws PiriNotConnectedException
    {
        // This command retrieves properties about a particular user
        // Attributes:  userName    -   User to retrieve properties about
        // If attribute not present, send error messager and return
        if (pCommand.doesParameterExist("userName") ==  false)
        {
            pConnection.sendError(pCommand, "userNameMissing", "User name attribute not supplied");
            return;
        }
        // Retrieve value of username we want to query
        String userName = pCommand.getParameter("userName");
        // Check user exists, if not send error
        if (mUsers.doesUserExist(userName) == false)
            pConnection.sendError(pCommand, "userNameNotFound", "The specified user name was not found");
        // Retrieve this user object and query properties
        User user = mUsers.getUser(userName);
        String userDisplayName = user.getDisplayName();
        Users.Group userGroup = user.getGroup();
        // Create our reply and fill in parameters
        Command reply = new Command("getUserProperties", null);
        reply.setParameter("userName", userName);
        reply.setParameter("displayName", userDisplayName);
        reply.setParameter("group", String.valueOf(userGroup));
        // Send reply
        pConnection.sendReply(pCommand, reply);
    }

    public void cmdSetUserProperty(Connection pConnection, Command pCommand) throws PiriNotConnectedException
    {
        // This command sets the properties of the calling user
        // OPTIONAL Attributes:
        //  contactAddress - New e-mail address
        //  websiteUrl - URL to website
        //

        // Check connection has a valid user
/*
        if (pConnection.getUserName() == null)
        {
            pConnection.sendError(pCommand, "requireLogin", "You need to login before issuing this command");
            return;
        }
        User user = mUsers.getUser(pConnection.getUserName());
        if (pCommand.doesParameterExist("contactAddress"))
            user.setContactAddress(pCommand.getParameter("contactAddress"));
        if (pCommand.doesParameterExist("websiteUrl"))
            user.setWebsiteUrl(pCommand.getParameter("websiteUrl"));
        // Tell user everything OK
        pConnection.sendOK(pCommand);
*/
    }

    private void cmdJoinRoom(Connection pConnection, Command pCommand)
    {

    }

    private boolean isUserOnline(String pUserName)
    {
        return true;
    }

    private boolean isUserModerator(String pUserName)
    {
        return true;
    }

    private boolean isUserAdministrator(String pUserName)
    {
        return true;
    }
}
