/*
 * Copyright (c) 2002-2007 TeamDev Ltd. All rights reserved.
 *
 * Use is subject to license terms.
 *
 * The complete licence text can be found at
 * http://www.teamdev.com/winpack/license.jsf
 */
package teamdev.jxcapture.samples.demo;

import org.jdesktop.application.Application;
import org.jdesktop.application.ApplicationContext;
import org.jdesktop.application.ResourceMap;

import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileView;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;

/**
 * @author Ikryanov Vladimir
 */
public class ImageFileChooser {

    private Component owner;

    public ImageFileChooser() {
        this(null);
    }

    public ImageFileChooser(Component owner) {
        this.owner = owner;
    }

    /**
     * Shows the file open dialog.
     *
     * @return the selected file or <code>null</code> if cancel actions has occured
     */
    public File openImageFile() {
        return showDialog(false);
    }

    /**
     * Shows the file save dialog.
     *
     * @return the selected file or <code>null</code> if cancel actions has occured
     */
    public File saveImageFile() {
        File imageFile = showDialog(true);
        if (imageFile != null && imageFile.exists()) {
            ApplicationContext context = Application.getInstance().getContext();
            ResourceMap resourceMap = context.getResourceMap(ImageFileChooser.class);
            String title = resourceMap.getString("fileExistsConfirmation.title");
            String message = resourceMap.getString("fileExistsConfirmation.message", imageFile.getName());
            int option = JOptionPane.showConfirmDialog(owner, message, title, JOptionPane.YES_NO_OPTION);
            if (option == JOptionPane.NO_OPTION) {
                ApplicationSettings settings = ApplicationSettings.getInstance();
                int index = settings.getTemplateNumber();
                settings.setTemplateNumber(--index);
                return saveImageFile();
            }
        }
        return imageFile;
    }

    private File showDialog(boolean save) {
        JFileChooser fileChooser = new JFileChooser();
        // removes the default file filter
        fileChooser.setAcceptAllFileFilterUsed(false);
        // sets the file filters to the file chooser dialog
        FileFilter[] filters = getFilters();
        for (FileFilter filter1 : filters) {
            fileChooser.addChoosableFileFilter(filter1);
        }
        if (!save) {
            fileChooser.addChoosableFileFilter(new AllImageFilesFilter());
        }
        // sets the file chooser preview
        fileChooser.setAccessory(new ImagePreview(fileChooser));
        // shows the file chooser dialog
        fileChooser.setDialogTitle(save ? "Save As" : "Open");
        if (save) {
            String name = getFileName();
            fileChooser.setSelectedFile(new File(name));
        }
        JFrame window = new JFrame();
        ApplicationContext context = Application.getInstance().getContext();
        ResourceMap resourceMap = context.getResourceMap(ImageViewer.class);
        window.setIconImage(resourceMap.getImageIcon("icon").getImage());
        Component parent = owner != null ? owner : window;
        int state = save ? fileChooser.showSaveDialog(parent) : fileChooser.showOpenDialog(parent);
        if (state == JFileChooser.APPROVE_OPTION) {
            File selectedFile = fileChooser.getSelectedFile();
            if (selectedFile != null) {
                // checks the extension of the selected file
                String fileName = selectedFile.getName();
                int index = fileName.lastIndexOf(".");
                if (index == -1) {
                    FileFilter fileFilter = fileChooser.getFileFilter();
                    ImageFileFilter filter = (ImageFileFilter) fileFilter;
                    String extension = filter.getExtension();
                    String absolutePath = selectedFile.getAbsolutePath();

                    return new File(absolutePath + "." + extension);
                }
                return selectedFile;
            }
        }
        ApplicationSettings settings = ApplicationSettings.getInstance();
        settings.setTemplateNumber(settings.getTemplateNumber() - 1);
        return null;
    }

    private String getFileName() {
        ApplicationSettings settings = ApplicationSettings.getInstance();
        String fileName = settings.getTemplateFileName();
        int index = settings.getTemplateNumber();
        settings.setTemplateNumber(++index);
        return fileName.replaceAll("#", String.valueOf(index));
    }

    /**
     * Gets all supported file filters.
     *
     * @return the array of <code>FileFilter</code> objects
     */
    public FileFilter[] getFilters() {
        ApplicationSettings settings = ApplicationSettings.getInstance();
        String[] descriptions = settings.getFormatDescriptions();
        String[] formats = settings.getImageFormats();
        ImageFileFilter[] filters = new ImageFileFilter[formats.length];
        for (int i = 0; i < formats.length; i++) {
            String[] extensions = settings.getFormatExtensions(formats[i]);
            if (extensions.length > 0) {
                filters[i] = new ImageFileFilter(extensions, descriptions[i]);
            }
        }
        return filters;
    }

    private class AllImageFilesFilter extends FileFilter {

        public boolean accept(File file) {
            if (file.isDirectory()) return true;
            String[] formats = ApplicationSettings.getInstance().getImageFormats();
            for (String format : formats) {
                if (file.getName().endsWith("." + format.toUpperCase())) return true;
                if (file.getName().endsWith("." + format.toLowerCase())) return true;
            }
            return false;
        }

        public String getDescription() {
            return "All Formats";
        }
    }

    private class ImageFileFilter extends FileFilter {
        private String[] extensions;
        private String description;

        public ImageFileFilter(String[] extensions, String description) {
            this.extensions = extensions;
            this.description = description;
        }

        public boolean accept(File file) {
            if (file.isFile()) {
                String name = file.getName();
                for (String extension : extensions) {
                    if (name.endsWith("." + extension)) return true;
                }
                return false;
            }
            return file.isDirectory();
        }

        public String getDescription() {
            return description;
        }

        public String getExtension() {
            return extensions[0];
        }

        public String toString() {
            return description;
        }
    }

    public class ImagePreview extends JComponent implements PropertyChangeListener {
        ImageIcon thumbnail = null;
        File file = null;

        public ImagePreview(JFileChooser fc) {
            setPreferredSize(new Dimension(100, 50));
            fc.addPropertyChangeListener(this);
        }

        public void loadImage() {
            if (file == null) {
                thumbnail = null;
                return;
            }

            ImageIcon tmpIcon = new ImageIcon(file.getPath());
            if (tmpIcon.getIconWidth() > 90) {
                thumbnail = new ImageIcon(tmpIcon.getImage(). getScaledInstance(90, -1, Image.SCALE_DEFAULT));
            } else {
                thumbnail = tmpIcon;
            }
        }

        public void propertyChange(PropertyChangeEvent e) {
            boolean update = false;
            String prop = e.getPropertyName();

            //If the directory changed, don't show an image.
            if (JFileChooser.DIRECTORY_CHANGED_PROPERTY.equals(prop)) {
                file = null;
                update = true;

                //If a file became selected, find out which one.
            } else if (JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equals(prop)) {
                file = (File) e.getNewValue();
                update = true;
            }

            //Update the preview accordingly.
            if (update) {
                thumbnail = null;
                if (isShowing()) {
                    loadImage();
                    repaint();
                }
            }
        }

        protected void paintComponent(Graphics g) {
            if (thumbnail == null) {
                loadImage();
            }
            if (thumbnail != null) {
                int x = getWidth() / 2 - thumbnail.getIconWidth() / 2;
                int y = getHeight() / 2 - thumbnail.getIconHeight() / 2;

                if (y < 0) y = 0;
                if (x < 5) x = 5;

                thumbnail.paintIcon(this, g, x, y);
            }
        }
    }
}

