
import java.io.*;
import java.util.*;

public class AlbumServlet extends PhotoApplicationServlet
{

    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response)
        throws ServletException,
        IOException
    {

        User user = getCurrentUser(request);
        if (user == null)
        {
            response.sendRedirect(LOGIN_PAGE_URL);
            return;
        }

        PrintWriter out = startWritingPage(response);

        String albumName = request.getParameter("album");
        if (!validateAlbumName(albumName, out))
            return;

        Album album = loadAlbumByName(albumName);
        if (!validateAlbum(album, out))
            return;

        AlbumPageModel model = new AlbumPageModel(album, request.getParameter("page"));
        new AlbumPage(model).printPage(out);

        out.flush();
    }

    private boolean validateAlbum(Album album, PrintWriter out)
    {
        boolean valid = true;
        if (album == null)
        {
            new ErrorPage("Could not load album '" + album.getName() + "'").printError(out);
            valid = false;
        }
        return valid;
    }

    private boolean validateAlbumName(String albumName, PrintWriter out)
    {
        boolean valid = true;
        if (albumName == null || albumName.equals(""))
        {
            new ErrorPage("Missing parameter: album").printError(out);
            valid = false;
        }
        return valid;
    }

    private PrintWriter startWritingPage(HttpServletResponse response)
    {
        response.setContentType("text/html");
        disableCache(response);
        PrintWriter out = response.getWriter();
        return out;
    }

    User getCurrentUser(HttpServletRequest request)
    {
        return (User) (request.getSession(true).getAttribute(CURRENT_USER_SESSION_ATTRIBUTE));
    }

    private void disableCache(HttpServletResponse response)
    {
        response.setHeader("Cache-Control", "no-cache"); //HTTP 1.1
        response.setHeader("Pragma", "no-cache"); //HTTP 1.0
        // prevents caching at the proxy server
        response.setHeader("Expires", "Thu, 01 Jan 1970 00:00:00 GMT");
    }
}

class Page
{
    protected void printHead(PrintWriter out, String title)
    {
        out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
        out.println("<html>");
        out.println("<head>");
        out.println("<title>" + title + "</title>");
        out.println("</head>");
    }
}

class AlbumPageModel
{
    private Album album;
    private String pageParameter;

    public AlbumPageModel(Album album, String pageParameter)
    {
        this.album = album;
        this.pageParameter = pageParameter;
    }

    public Album getAlbum()
    {
        return album;
    }

    public void setAlbum(Album album)
    {
        this.album = album;
    }

    public int getPicturesPerPage()
    {
        return PICTURES_PER_PAGE;
    }

    private static final int PICTURES_PER_PAGE = 20;

    public int getPageNumber()
    {
        int page;
        if (pageParameter == null || pageParameter.equals(""))
        {
            page = 0;
        }
        else
        {
            page = Integer.parseInt(pageParameter);
        }
        return page;
    }

    public List getPictures()
    {
        List pictures = new ArrayList();
        int start = getStart();
        int end = getEnd();
        end = Math.min(end, getAlbum().getPictures().size());
        for (int i = start; i < end; ++i)
        {
            pictures.add(getAlbum().getPictures().get(i));
        }
        return pictures;
    }

    public int getEnd()
    {
        int end = getStart() + getPicturesPerPage();
        return end;
    }

    public int getStart()
    {
        int start = getPageNumber() * getPicturesPerPage();
        return start;
    }

    public int getTotalPictures()
    {
        return getAlbum().getPictures().size();
    }
}

class AlbumPage extends Page
{
    private AlbumPageModel model;

    public AlbumPage(AlbumPageModel model)
    {
        this.setModel(model);
    }

    public AlbumPageModel getModel()
    {
        return model;
    }

    public void setModel(AlbumPageModel model)
    {
        this.model = model;
    }

    public void printPage(PrintWriter out)
    {
        String title = "Album: " + getModel().getAlbum().getName();
        printHead(out, title);
        out.println("<body>");

        out.println("<h1>" + title + "</h1>");

        printPictureTable(out);
        printPreviousAndNextLinks(out, getModel().getPageNumber());
    }

    private void printPreviousAndNextLinks(PrintWriter out, int pageNumber)
    {
        // todo: refactor me!
        out.println("<center>");
        if (pageNumber > 0)
        {
            out.print("<a href='?page=" + (pageNumber - 1) + "'>&lt;&lt; previous</a>&nbsp;");
        }
        if (getModel().getEnd() < getModel().getTotalPictures())
        {
            out.print("&nbsp;<a href='?page=" + (pageNumber + 1) + "'>next &gt;&gt;</a>");
        }
        out.println("<center>");
    }

    private void printPictureTable(PrintWriter out)
    {
        out.println("<table border=0>");

        List pictures = getModel().getPictures();

        for (Iterator pictureIterator = pictures.iterator(); pictureIterator.hasNext(); )
        {
            Picture picture = (Picture) pictureIterator.next();
            printPicture(out, picture);
        }

        out.println("</table>");
    }

    private void printPicture(PrintWriter out, Picture picture)
    {
        out.print("<tr><td><a href='" + picture.getImageSource() + "'>");
        out.print("<img src='" + picture.getThumbnailImageSource() + "' border='0'>");
        out.print("</a>");
        out.print("</td>");
        out.print("<td>");
        out.print(picture.getCaption());
        out.print("</td>");
        out.println("</tr>");
    }

    public void printError(PrintWriter out, String message)
    {
        printHead(out, "Error");
        out.println("<body><p class='error'>");
        out.print(message);
        out.print("</p></body>");
        out.println("</html>");
    }

}

class ErrorPage extends Page
{
    String message;

    public ErrorPage(String message)
    {
        this.message = message;
    }

    // todo: rename to "printPage" and make it an abstract method of Page
    public void printError(PrintWriter out)
    {
        printHead(out, "Error");
        out.println("<body><p class='error'>");
        out.print(message);
        out.print("</p></body>");
        out.println("</html>");
    }
}

