/*
 * 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.Action;
import org.jdesktop.application.ApplicationContext;
import org.jdesktop.application.ResourceMap;
import org.jdesktop.application.Application;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.BorderUIResource;
import java.awt.*;
import java.io.File;

/**
 * @author Ikryanov Vladimir
 */
public class SettingsDialog extends EscapeDialog {

    private static SettingsDialog instance;

    private JCheckBox delay = new JCheckBox();
    private JCheckBox includeCursor = new JCheckBox();
    private JCheckBox transparentWindows = new JCheckBox();
    private JCheckBox autoSave = new JCheckBox();

    private JLabel folderLabel = new JLabel();
    private JLabel formatLabel = new JLabel();
    private JLabel delayTimeLabel = new JLabel();

    private JTextField outputFolder;
    private JTextField templateName;

    private JSpinner templateNumber = new JSpinner();
    private JSpinner delayTime = new JSpinner();

    private JComboBox formats;

    private JButton chooseFolder = new JButton();

    private ActionMap actionMap;
    private ResourceMap resourceMap;
    private ApplicationSettings settings = ApplicationSettings.getInstance();

    private SettingsDialog() {
        ApplicationContext context = Application.getInstance().getContext();
        actionMap = context.getActionMap(SettingsDialog.class, this);
        resourceMap = context.getResourceMap(SettingsDialog.class);

        createGUI();

        setName("dialog");
        setModal(true);
        setResizable(false);
        setIconImage(resourceMap.getImageIcon("window.icon").getImage());
        setLocationRelativeTo(null);

        resourceMap.injectComponents(this);
    }

    public static SettingsDialog getInstance() {
        return instance == null ? instance = new SettingsDialog() : instance;
    }

    private void createGUI() {
        JPanel contentPane = new JPanel(new GridBagLayout());
        contentPane.add(createContentPane(), new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
        contentPane.add(Box.createGlue(), new GridBagConstraints(0, 1, 1, 1, 0.0, 1.0,
                GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
        contentPane.add(createActionPane(), new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
        contentPane.setBorder(new EmptyBorder(10, 10, 10, 10));

        setContentPane(contentPane);

        pack();
    }

    private JPanel createContentPane() {
        JPanel mainPane = new JPanel(new GridBagLayout());
        mainPane.add(createCapturePane(), new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
        mainPane.add(createFilePane(), new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
        return mainPane;
    }

    private JPanel createFilePane() {
        JPanel contentPane = new JPanel(new GridBagLayout());
        contentPane.setBorder(new BorderUIResource.TitledBorderUIResource(resourceMap.getString("filePanel.title")));

        templateName = new JTextField(settings.getTemplateFileName(), 10);
        int value = settings.getTemplateNumber();
        SpinnerModel spinnerModel = new SpinnerNumberModel(value, 0, 1000, 1);
        templateNumber.setModel(spinnerModel);
        templateNumber.setPreferredSize(new Dimension(45, 20));
        outputFolder = new JTextField(settings.getOutputFolder(), 20);
        chooseFolder.setPreferredSize(new Dimension(20, 20));
        formats = new JComboBox(settings.getImageFormats());
        formats.setPreferredSize(new Dimension(60, 20));
        formats.setSelectedIndex(settings.getImageFormatIndex());

        JPanel fileChoosePane = new JPanel(new GridBagLayout());
        fileChoosePane.add(outputFolder, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 3), 0, 0));
        fileChoosePane.add(chooseFolder, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 3, 0, 0), 0, 0));

        chooseFolder.setAction(actionMap.get("chooseFolder"));

        folderLabel.setName("folderLabel");
        formatLabel.setName("formatLabel");

        autoSave.setAction(actionMap.get("autoSave"));
        autoSave.setSelected(settings.isAutoSave());

        JLabel fileNameTemplate = new JLabel();
        fileNameTemplate.setName("fileNameTemplate");

        JLabel startsFrom = new JLabel();
        startsFrom.setName("startsFrom");

        contentPane.add(fileNameTemplate, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.WEST, new Insets(0, 10, 0, 0), 0, 0));
        contentPane.add(templateName, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 6, 0, 3), 0, 0));
        contentPane.add(startsFrom, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.WEST, new Insets(0, 3, 0, 3), 0, 0));
        contentPane.add(this.templateNumber, new GridBagConstraints(3, 0, 2, 1, 0.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 3, 0, 10), 0, 0));
        contentPane.add(autoSave, new GridBagConstraints(0, 1, 4, 1, 1.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.WEST, new Insets(11, 10, 0, 0), 0, 0));
        contentPane.add(folderLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0,
                GridBagConstraints.EAST, GridBagConstraints.EAST, new Insets(7, 3, 0, 3), 0, 0));
        contentPane.add(fileChoosePane, new GridBagConstraints(1, 2, 4, 1, 0.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(7, 3, 0, 10), 0, 0));
        contentPane.add(formatLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0,
                GridBagConstraints.EAST, GridBagConstraints.EAST, new Insets(7, 3, 10, 3), 0, 0));
        contentPane.add(formats, new GridBagConstraints(1, 3, 1, 1, 0.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.WEST, new Insets(7, 3, 10, 10), 0, 0));

        updateAutoSave();

        return contentPane;
    }

    private JPanel createCapturePane() {
        includeCursor.setName("includeCursor");
        includeCursor.setSelected(settings.isIncludeCursor());

        transparentWindows.setName("captureTransparentWindows");
        transparentWindows.setSelected(settings.isCaptureTransparentWindows());

        JPanel contentPane = new JPanel(new GridBagLayout());
        contentPane.setBorder(new BorderUIResource.TitledBorderUIResource(" Capture "));
        contentPane.add(includeCursor, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.WEST, new Insets(0, 10, 3, 10), 0, 0));
        contentPane.add(transparentWindows, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.WEST, new Insets(0, 10, 3, 10), 0, 0));
        contentPane.add(createDelayTimePane(), new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.WEST, new Insets(0, 0, 0, 0), 0, 0));
        return contentPane;
    }

    private JPanel createDelayTimePane() {
        int value = settings.getDelayTime() / 1000;
        int maximum = settings.getMaxDelayTime() / 1000;
        delayTime.setModel(new SpinnerNumberModel(value, 1, maximum, 1));
        delayTime.setPreferredSize(new Dimension(50, 20));

        delay.setAction(actionMap.get("delayBeforeCapture"));
        delay.setSelected(settings.isDelayBeforeCapture());

        delayTimeLabel.setName("seconds");

        JPanel delayTimePane = new JPanel(new GridBagLayout());
        delayTimePane.add(delay, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 10, 10, 0), 0, 0));
        delayTimePane.add(delayTime, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 3, 10, 3), 0, 0));
        delayTimePane.add(delayTimeLabel, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 3, 10, 10), 0, 0));

        updateDelayArea();

        return delayTimePane;
    }

    private JPanel createActionPane() {
        Dimension buttonSize = new Dimension(75, 23);

        JButton okButton = new JButton(actionMap.get("apply"));
        okButton.setPreferredSize(buttonSize);

        JButton cancelButton = new JButton(actionMap.get("cancel"));
        cancelButton.setPreferredSize(buttonSize);

        JPanel actionPane = new JPanel(new GridBagLayout());
        actionPane.add(Box.createHorizontalGlue(), new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
        actionPane.add(okButton, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
        actionPane.add(cancelButton, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 6, 0, 0), 0, 0));
        actionPane.setBorder(new EmptyBorder(10, 0, 0, 0));

        return actionPane;
    }

    private void updateDelayArea() {
        boolean selected = delay.isSelected();
        delayTime.setEnabled(selected);
        delayTimeLabel.setEnabled(selected);
    }

    private void updateAutoSave() {
        boolean selected = autoSave.isSelected();
        folderLabel.setEnabled(selected);
        formatLabel.setEnabled(selected);
        outputFolder.setEnabled(selected);
        chooseFolder.setEnabled(selected);
        formats.setEnabled(selected);
    }

    private String getOutputFolder() {
        String outputPath = outputFolder.getText();
        if (outputPath.length() == 0) {
            String title = resourceMap.getString("erremptyFolderError.title");
            String message = resourceMap.getString("emptyFolderError.message");
            JOptionPane.showMessageDialog(SettingsDialog.this, message, title, JOptionPane.ERROR_MESSAGE);
            return null;
        } else if (!new File(outputPath).exists()) {
            String title = resourceMap.getString("existFolderError.title");
            String message = resourceMap.getString("existFolderError.message");
            JOptionPane.showMessageDialog(SettingsDialog.this, message, title, JOptionPane.ERROR_MESSAGE);
            return null;
        }
        return outputPath;
    }

    @Action
    public void delayBeforeCapture() {
        updateDelayArea();
    }

    @Action
    public void autoSave() {
        updateAutoSave();
    }

    @Action
    public void chooseFolder() {
        JFileChooser chooser = new JFileChooser();
        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int result = chooser.showOpenDialog(SettingsDialog.this);
        if (result == JFileChooser.APPROVE_OPTION) {
            String absolutePath = chooser.getSelectedFile().getAbsolutePath();
            outputFolder.setText(absolutePath);
        }
    }

    @Action
    public void apply() {
        String fileNameTemplate = templateName.getText();
        if (fileNameTemplate.length() == 0) {
            String title = resourceMap.getString("emptyFileNameError.title");
            String message = resourceMap.getString("emptyFileNameError.message");
            JOptionPane.showMessageDialog(SettingsDialog.this, message, title, JOptionPane.ERROR_MESSAGE);
            return;
        }
        if (autoSave.isSelected()) {
            String outputPath = getOutputFolder();
            if (outputPath == null) return;
            settings.setOutputFolder(outputPath);
            settings.setImageFormatIndex(formats.getSelectedIndex());
        }
        settings.setIncludeCursor(includeCursor.isSelected());
        settings.setCaptureTransparentWindows(transparentWindows.isSelected());
        settings.setAutoSave(autoSave.isSelected());
        settings.setTemplateFileName(fileNameTemplate);
        settings.setTemplateNumber((Integer) templateNumber.getValue());
        settings.setDelayBeforeCapture(SettingsDialog.this.delay.isSelected());
        if (settings.isDelayBeforeCapture()) {
            settings.setDelayTime((Integer) delayTime.getValue() * 1000);
        }

        destroy();
    }

    @Action
    public void cancel() {
        destroy();
    }

    private void destroy() {
        instance.dispose();
        instance = null;
    }
}