package page.example;


import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.wikiwebserver.core.WareHouse;
import org.wikiwebserver.handler.http.FormData;
import org.wikiwebserver.handler.http.HTTPException;
import org.wikiwebserver.handler.http.interfaces.HTTPResponder;
import page.config.SiteTemplatedPage;
import page.image.ImageResizer;

import org.wikiwebserver.util.comparator.FileNameComparator;

import static org.wikiwebserver.html.HTMLHelper.*;


public class ImageGallery extends SiteTemplatedPage implements HTTPResponder {

    private final int THUMBNAIL_WIDTH = 150;
    private final int SHOW_WIDTH = 690;
    
    public void generate() throws HTTPException {
        
        setTitle("Image Gallery - WikiWebServer.org");
        addResourceRoot("/templates/default/gallery/");
        addCSSLink("gallery.css");
        
        File file = new File("gallery");
        FormData formData = getFormData();
        if (formData != null) {
            String fileString = formData.getFirst("file");
            if (fileString != null) {
                if (fileString.startsWith("/")) {
                    fileString = fileString.substring(1);
                    if (fileString.length() == 0) fileString = ".";
                }
                file = new File(fileString);
            }
        }
        
        append("<h1>Image Gallery</h1>");
        
        try {
            file = file.getCanonicalFile();
            
            File parent = file.getParentFile();
            if (parent != null && !parent.equals(new File("./"))) {
                String path = getPath(parent);
                String view = getUrl() + "?file=" + WareHouse.formDataEncode(path);
                //append("<p><b>" +  a(view, "Up a level") + "</b></p>");
            }
            
        } catch (SecurityException ex) {
            // thrown by getPath when adding parent link (ignore)
        } catch (IOException ex) {
            throw new HTTPException(404, "Directory or image expected");
        }
        

        
        if (file.isDirectory()) {
            List<File> dirFiles = sortFiles(getDirectories(file));    
            append(getDirectoryLinks(dirFiles));  
            
            List<File> imageFiles = sortFiles(getImages(file)); 
            if (imageFiles.size() > 0) {
                String ssUrl = WareHouse.getUrlPathForClass(page.example.ImageSlideShow.class)
                             + "?path=" + WareHouse.formDataEncode(getPath(file));
                String ttUrl = "http://slideshow.triptracker.net/";

                append(getImageThumbnails(imageFiles)); 
                
                append("<div style='clear: both;'></div>");
                append("<p><b>" +  a(ssUrl, "View Slideshow") + "</b>" +
                        " - Powered by " + a(ttUrl, "TripTracker Slideshow") + "</p>");                
            } else {
                append("<p>No images found in this directory</p>");
            }
        }
        else {            
            if (isImage(file)) {
                String path = getPath(file);
                append("<div class='largeImageDiv'>" +
                       thumbnail(path, file.getName(), SHOW_WIDTH) +
                       "</div>");
                
                String resizer = WareHouse.getUrlPathForClass(page.image.ImageResizer.class);
                int minDim = ImageResizer.getMinDimension(path.substring(1));
                
                int[] sizes = { 640, 800, 1024, 1200, 1600 };
                
                append("<h1>Other sizes</h1>");
                append("<ul>");
                for (int size : sizes) {
                    if (minDim > size) {
                        String view = resizer + "?path=" + 
                                      WareHouse.formDataEncode(path) + "&amp;s=" + size;
                        append("<li>" + a(view, size + " pixels") + "</li>");
                    }
                }   
                append("<li>" + a(path, "Original resolution") + "</li></ul>");
            }        
        }
            
        append("<div style='clear: both;'></div>");        
    }
    
    private String getImageThumbnails(List<File> images) {
        StringBuilder buffer = new StringBuilder();
        for (File image : images) {
            String path = getPath(image);
            String view = getUrl() + "?file=" + WareHouse.formDataEncode(path);
            buffer.append("<div class='outerThumbnailDiv'>" +
                          "<div class='innerThumbnailDiv'>" +
                          a(view, thumbnail(path, image.getName(), THUMBNAIL_WIDTH)) +
                          "</div></div>");
        }
        return buffer.toString();
    }
    
    private String getDirectoryLinks(List<File> dir) {
        if (dir == null || dir.size() == 0) {
            return "";
        }
        
        StringBuilder buffer = new StringBuilder();
        buffer.append("<ul>");
        for (File subDir : dir) {
            String path = getPath(subDir);
            String view = getUrl() + "?file=" + WareHouse.formDataEncode(path);
            buffer.append("<li>" +  a(view, subDir.getName()) + "</li>");
        }
        buffer.append("</ul>");
        return buffer.toString();
    }    
    
    private List<File> getImages(File dir) {
        List<File> images = new ArrayList<File>();
        
        File[] files = dir.listFiles();
        for (File file : files) {
            if (isImage(file)) {
                images.add(file);
            }
        }
        
        return images;
    }
    
    private List<File> getDirectories(File dir) {
        List<File> dirs = new ArrayList<File>();
        
        File[] files = dir.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
                dirs.add(file);
            }
        }
        
        return dirs;
    }    
    
    private List<File> sortFiles(List<File> files) {

        Collections.sort(files, new FileNameComparator());
        
        return files;
    }    
    
    private String getPath(File file) {
        try {
            File base = new File(".").getCanonicalFile();
            file = file.getCanonicalFile();         
            
            if (!file.toString().startsWith(base.toString())) {
                throw new SecurityException("Attempt to access outside wiki root");
            }
            String path = file.toString().substring(base.toString().length());
            
            if (path.length() == 0) path = "/";
            
            return path.replace("\\", "/");
            
        } catch (IOException ex) {
            throw new SecurityException("Invalid path");
        }
    }    
    
    private boolean isImage(File file) {
        String[] imageHints = { "jpg", "gif", "jpeg" };
        for (String hint : imageHints) {
            if (file.getName().toLowerCase().endsWith(hint)) {
                return true;
            }
        }
        return false;
    }
}