/*
 * SK's Minecraft Launcher
 * Copyright (C) 2010-2014 Albert Pham <http://www.sk89q.com> and contributors
 * Please see LICENSE.txt for license information.
 */

package com.skcraft.launcher.buildtools.project;

import com.google.common.base.Joiner;
import com.skcraft.launcher.builder.BuilderConfig;
import com.skcraft.launcher.builder.FeaturePattern;
import com.skcraft.launcher.builder.FnPatternList;
import com.skcraft.launcher.model.modpack.LaunchModifier;
import com.skcraft.launcher.swing.SwingHelper;
import net.miginfocom.swing.MigLayout;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class BuilderConfigDialog extends JDialog {

    private static final Joiner NEW_LINE_JOINER = Joiner.on("\n");

    private final JTextField nameText = new JTextField(20);
    private final JTextField titleText = new JTextField(30);
    private final JTextField gameVersionText = new JTextField(10);
    private final JTextArea launchFlagsArea = new JTextArea(10, 40);
    private final JTextArea userFilesIncludeArea = new JTextArea(15, 40);
    private final JTextArea userFilesExcludeArea = new JTextArea(8, 40);
    private final FeaturePatternTable featuresTable = new FeaturePatternTable();
    private FeaturePatternTableModel featuresModel;

    private final BuilderConfig config;
    private boolean saved = false;

    public BuilderConfigDialog(Window parent, BuilderConfig config) {
        super(parent, "Edit modpack.json", ModalityType.DOCUMENT_MODAL);

        this.config = config;

        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        initComponents();
        setResizable(false);
        pack();
        setLocationRelativeTo(parent);

        copyFrom();
    }

    private void initComponents() {
        launchFlagsArea.setFont(nameText.getFont());
        userFilesIncludeArea.setFont(nameText.getFont());
        userFilesExcludeArea.setFont(nameText.getFont());

        JTabbedPane tabbedPane = new JTabbedPane();

        JPanel container = new JPanel();
        container.setLayout(new MigLayout("fill, insets dialog"));

        tabbedPane.addTab("Modpack", null, createMainPanel());
        tabbedPane.addTab("Launch", null, createLaunchPanel());
        tabbedPane.addTab("User Files", null, createUserFilesPanel());
        tabbedPane.addTab("Optional Features", null, createFeaturesPanel());

        container.add(tabbedPane, "span, grow, gapbottom unrel");

        JButton saveButton = new JButton("Save");
        JButton cancelButton = new JButton("Cancel");

        container.add(saveButton, "tag ok, span, split 2, sizegroup bttn");
        container.add(cancelButton, "tag cancel, sizegroup bttn");

        add(container, BorderLayout.CENTER);

        saveButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (nameText.getText().trim().isEmpty()) {
                    SwingHelper.showErrorDialog(BuilderConfigDialog.this, "The 'Name' field cannot be empty.", "Input Error");
                    return;
                }

                if (gameVersionText.getText().trim().isEmpty()) {
                    SwingHelper.showErrorDialog(BuilderConfigDialog.this, "The 'Game Version' field must be a Minecraft version.", "Input Error");
                    return;
                }

                copyTo();
                saved = true;
                dispose();
            }
        });

        cancelButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                dispose();
            }
        });
    }

    private JPanel createMainPanel() {
        JPanel container = new JPanel();
        SwingHelper.removeOpaqueness(container);
        container.setLayout(new MigLayout("insets dialog"));

        container.add(new JLabel("Name:"));
        container.add(nameText, "span");

        container.add(new JLabel("Title:"));
        container.add(titleText, "span");

        container.add(new JLabel("Game Version:"));
        container.add(gameVersionText, "span");

        return container;
    }

    private JPanel createLaunchPanel() {
        JPanel container = new JPanel();
        SwingHelper.removeOpaqueness(container);
        container.setLayout(new MigLayout("insets dialog"));

        container.add(new JLabel("Launch Flags:"), "wrap");
        container.add(SwingHelper.wrapScrollPane(launchFlagsArea), "span");

        return container;
    }

    private JPanel createUserFilesPanel() {
        JPanel container = new JPanel();
        SwingHelper.removeOpaqueness(container);
        container.setLayout(new MigLayout("insets dialog"));

        container.add(new JLabel("Include Patterns:"), "wrap");
        container.add(SwingHelper.wrapScrollPane(userFilesIncludeArea), "span, gapbottom unrel");

        container.add(new JLabel("Exclude Patterns:"), "wrap");
        container.add(SwingHelper.wrapScrollPane(userFilesExcludeArea), "span");

        return container;
    }

    private JPanel createFeaturesPanel() {
        JPanel container = new JPanel();
        SwingHelper.removeOpaqueness(container);
        container.setLayout(new MigLayout("fill, insets dialog"));

        JButton newButton = new JButton("New...");
        JButton editButton = new JButton("Edit...");
        JButton deleteButton = new JButton("Delete...");

        container.add(newButton, "span, split 3, sizegroup bttn");
        container.add(editButton, "sizegroup bttn");
        container.add(deleteButton, "sizegroup bttn");

        container.add(SwingHelper.wrapScrollPane(featuresTable), "grow, w 10:100:null, gaptop 10");

        newButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                FeaturePattern pattern = new FeaturePattern();
                if (FeaturePatternDialog.showEditor(BuilderConfigDialog.this, pattern)) {
                    featuresModel.addFeature(pattern);
                }
            }
        });

        editButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int index = featuresTable.getSelectedRow();
                if (index > -1) {
                    FeaturePattern pattern = featuresModel.getFeature(index);
                    FeaturePatternDialog.showEditor(BuilderConfigDialog.this, pattern);
                    featuresModel.fireTableDataChanged();
                } else {
                    SwingHelper.showErrorDialog(BuilderConfigDialog.this, "Select a feature first.", "No Selection");
                }
            }
        });

        deleteButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int index = featuresTable.getSelectedRow();
                if (index > -1) {
                    FeaturePattern pattern = featuresModel.getFeature(index);
                    if (SwingHelper.confirmDialog(BuilderConfigDialog.this, "Are you sure that you want to delete '" + pattern.getFeature().getName() + "'?", "Delete")) {
                        featuresModel.removeFeature(index);
                    }
                } else {
                    SwingHelper.showErrorDialog(BuilderConfigDialog.this, "Select a feature first.", "No Selection");
                }
            }
        });

        return container;
    }

    private void copyFrom() {
        SwingHelper.setTextAndResetCaret(nameText, config.getName());
        SwingHelper.setTextAndResetCaret(titleText, config.getTitle());
        SwingHelper.setTextAndResetCaret(gameVersionText, config.getGameVersion());
        SwingHelper.setTextAndResetCaret(launchFlagsArea, NEW_LINE_JOINER.join(config.getLaunchModifier().getFlags()));
        SwingHelper.setTextAndResetCaret(userFilesIncludeArea, NEW_LINE_JOINER.join(config.getUserFiles().getInclude()));
        SwingHelper.setTextAndResetCaret(userFilesExcludeArea, NEW_LINE_JOINER.join(config.getUserFiles().getExclude()));
        featuresModel = new FeaturePatternTableModel(config.getFeatures());
        featuresTable.setModel(featuresModel);
    }

    private void copyTo() {
        config.setName(nameText.getText().trim());
        config.setTitle(titleText.getText().trim());
        config.setGameVersion(gameVersionText.getText().trim());

        LaunchModifier launchModifier = config.getLaunchModifier();
        FnPatternList userFiles = config.getUserFiles();

        launchModifier.setFlags(SwingHelper.linesToList(launchFlagsArea.getText()));
        userFiles.setInclude(SwingHelper.linesToList(userFilesIncludeArea.getText()));
        userFiles.setExclude(SwingHelper.linesToList(userFilesExcludeArea.getText()));
    }

    public static boolean showEditor(Window window, BuilderConfig config) {
        BuilderConfigDialog dialog = new BuilderConfigDialog(window, config);
        dialog.setVisible(true);
        return dialog.saved;
    }

}
