
/* Josh Holtrop
 * 2008-12-04
 * CS656
 * Lab 4
 */

import java.io.IOException;
import java.util.*;

import org.restlet.Context;
import org.restlet.data.Form;
import org.restlet.data.MediaType;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.resource.Resource;
import org.restlet.data.Status;
import org.restlet.resource.DomRepresentation;
import org.restlet.resource.Representation;
import org.restlet.resource.Variant;
import org.w3c.dom.*;

import com.db4o.ObjectContainer;
import com.db4o.query.Predicate;

/**
 * This is a Resource class for handling a single User object.
 *
 * You can GET a representation of the user, PUT to modify it, or DELETE it.
 */
public class UserResource extends Resource
{
    private User myUser;

    /* Construct the resource and initialize myUser */
    public UserResource(Context context, Request request, Response response)
    {
        super(context, request, response);
        String name = (String) request.getAttributes().get("id");
        myUser = findUser(name);
        if(myUser != null)
        {
            getVariants().add(new Variant(MediaType.TEXT_XML));
        }
    }

    /**
     * Returns the parent application.
     *
     * @return the parent application.
     */
    public ChatServer getApplication()
    {
        return (ChatServer) getContext().getAttributes().get(ChatServer.KEY);
    }

    /**
     * Returns the database container.
     *
     * @return the database container.
     */
    public ObjectContainer getContainer()
    {
        return getApplication().getContainer();
    }

    /**
     * Finds the user resource info in the database.
     * @param name The name of the user to be found.
     * @return The a reference to a User instance or null if there is none.
     */
    public User findUser(final String name)
    {
        User result = null;

        if (name != null)
        {
            // Create the query predicate
            Predicate<User> predicate = new Predicate<User>()
            {
                private static final long serialVersionUID = 1L;

                @Override
                public boolean match(User candidate)
                {
                    return name.equals(candidate.getUserName());
                }
            };

            // Query the database and get the first result
            List<User> users = getContainer().query(predicate);
            if ((users != null) && (users.size() > 0))
            {
                result = users.get(0);
            }
        }

        return result;
    }

    /**
     * handle HTTP GET requests.
     */
    @Override
    public Representation getRepresentation(Variant variant)
    {
        DomRepresentation rep = null;
        if (variant.getMediaType().equals(MediaType.TEXT_XML))
        {
            try
            {
                if (myUser != null)
                {
                    rep = myUser.getDomRepresentation();
                }
                else
                {
                    rep = new DomRepresentation(MediaType.TEXT_XML);
                    getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);
                }
                rep.getDocument().normalizeDocument();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
        return rep;
    }

    @Override
    public boolean allowDelete()
    {
        return true;
    }

    @Override
    public void delete()
    {
        if (myUser != null)
        {
            getContainer().delete(myUser);
            getContainer().commit();
            getResponse().setStatus(Status.SUCCESS_OK);
        }
        else
        {
            getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);
        }
    }

    /**
     * PUT is implemented.
     */
    @Override
    public boolean allowPut()
    {
        return true;
    }

    /**
     * Update a resource in response to an HTTP PUT call.
     */
    @Override
    public void put(Representation entity)
    {
        try
        {
            if (entity.getMediaType().equals(MediaType.APPLICATION_WWW_FORM, true)
                && (myUser != null))
            {
                // Parse the entity as a web form
                Form form = new Form(entity);

                // update the loaded User object
                String value = form.getFirstValue("user[host]");
                if (value != null)
                {
                    myUser.setHost(value);
                }

                value = form.getFirstValue("user[port]");
                if (value != null)
                {
                    myUser.setPort(Integer.parseInt(value));
                }

                value = form.getFirstValue("user[status]");
                if (value != null)
                {
                    myUser.setStatus(value.equals("available"));
                }

                // commit the changes.
                getContainer().set(myUser);
                getContainer().commit();

                getResponse().setStatus(Status.SUCCESS_OK);
                getResponse().setEntity(myUser.getDomRepresentation());
            }
            else
            {
                getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);
            }
        }
        catch (IOException e)
        {
            getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
            e.printStackTrace();
        }
    }
}
