/*
 * $Id$
 *
 * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
package com.sun.javatest.exec;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.net.URL;
import java.text.DateFormat;
import java.util.Date;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import com.sun.javatest.InterviewParameters;
import com.sun.javatest.Parameters.ExcludeListParameters;
import com.sun.javatest.Parameters.MutableExcludeListParameters;
import com.sun.javatest.TestSuite;
import com.sun.javatest.WorkDirectory;
import com.sun.javatest.tool.EditableFileList;
import com.sun.javatest.tool.FileChooser;
import com.sun.javatest.tool.UIFactory;

/**
 * Standard values view, exclude list panel.
 */
class CE_ExcludeListPane extends CE_StdPane
{
    CE_ExcludeListPane(UIFactory uif, InterviewParameters config) {
        super(uif, config, "excl");

        updateConfig();
        initGUI();
    }

    boolean isOKToClose() {
        if (mutableExcludeListParameters == null)
            return true;

        if (noneBtn.isSelected())
            return true;
        else if (initialBtn.isSelected())
            return initialPanel.isOKToClose();
        else if (latestBtn.isSelected())
            return latestPanel.isOKToClose();
        else if (customBtn.isSelected())
            return customPanel.isOKToClose();
        else
            throw new Error();
    }

    void updateConfig() {
        if (config == null)
            return;

        excludeListParameters = config.getExcludeListParameters();
        if (excludeListParameters instanceof MutableExcludeListParameters)
            mutableExcludeListParameters = (MutableExcludeListParameters) excludeListParameters;
        else
            mutableExcludeListParameters = null;
    }

    void load() {
        updateConfig();

        if (mutableExcludeListParameters != null) {
            int mode = mutableExcludeListParameters.getExcludeMode();
            switch (mode) {
            case MutableExcludeListParameters.NO_EXCLUDE_LIST:
                noneBtn.setSelected(true);
                break;

            case MutableExcludeListParameters.INITIAL_EXCLUDE_LIST:
                initialBtn.setSelected(true);
                break;

            case MutableExcludeListParameters.LATEST_EXCLUDE_LIST:
                latestBtn.setSelected(true);
                break;

            case MutableExcludeListParameters.CUSTOM_EXCLUDE_LIST:
                customBtn.setSelected(true);
                break;
            }

            TestSuite testSuite = config.getTestSuite();
            WorkDirectory workDir = config.getWorkDirectory();

            noneBtn.setEnabled(true);

            File initialExcludeList = testSuite.getInitialExcludeList();
            initialBtn.setEnabled(initialExcludeList != null);
            initialPanel.load(initialExcludeList);

            URL latestExcludeListURL = testSuite.getLatestExcludeList();
            File latestExcludeListFile = workDir.getSystemFile("latest.jtx");
            latestBtn.setEnabled(latestExcludeListURL != null);
            latestPanel.load(latestExcludeListURL, latestExcludeListFile);

            customBtn.setEnabled(true);
            customPanel.load();
            customPanel.setEnabled(true);
        }
        else {
            noneBtn.setEnabled(false);
            initialBtn.setEnabled(false);
            latestBtn.setEnabled(false);

            customBtn.setSelected(true);
            customBtn.setEnabled(false);
            customPanel.clear();
            customPanel.setEnabled(false);
        }
    }

    void save() {
        if (mutableExcludeListParameters != null) {
            int mode;
            if (customBtn.isSelected())
                mode = MutableExcludeListParameters.CUSTOM_EXCLUDE_LIST;
            else if (initialBtn.isSelected())
                mode = MutableExcludeListParameters.INITIAL_EXCLUDE_LIST;
            else if (latestBtn.isSelected())
                mode = MutableExcludeListParameters.LATEST_EXCLUDE_LIST;
            else
                mode = MutableExcludeListParameters.NO_EXCLUDE_LIST;
            mutableExcludeListParameters.setExcludeMode(mode);

            // no values to save from blankPanel and initialPanel
            latestPanel.save();
            customPanel.save();
        }
    }

    void setCheckExcludeListListener(ActionListener l) {
        latestPanel.setCheckExcludeListListener(l);
    }

    private void initGUI() {
        JPanel p = uif.createPanel("ce.excl", new BorderLayout(), false);

        initToolBar();
        p.add(toolBar, BorderLayout.WEST);

        body = uif.createPanel("ce.excl.body", new CardLayout(), false);
        body.setBorder(BorderFactory.createEtchedBorder());

        blankPanel = uif.createPanel("ce.excl.blank");
        blankPanel.setName("blank");
        body.add(blankPanel, blankPanel.getName());

        customPanel = new CustomPanel();
        body.add(customPanel, customPanel.getName());

        initialPanel = new InitialPanel();
        body.add(initialPanel, initialPanel.getName());

        latestPanel = new LatestPanel();
        body.add(latestPanel, latestPanel.getName());

        p.add(body, BorderLayout.CENTER);

        addBody(p);

        if (mutableExcludeListParameters == null)
            // can't accurately render info about the exclude list,
            // so mark the pane disabled
            setEnabled(false);
    }

    private void initToolBar() {
        toolBar = new JToolBar(JToolBar.VERTICAL);
        toolBar.setFloatable(false);

        btnGrp = new ButtonGroup();
        noneBtn = uif.createRadioButton("ce.excl.none", btnGrp);
        noneBtn.addChangeListener(listener);
        toolBar.add(noneBtn);

        initialBtn = uif.createRadioButton("ce.excl.initial", btnGrp);
        initialBtn.addChangeListener(listener);
        toolBar.add(initialBtn);

        latestBtn = uif.createRadioButton("ce.excl.latest", btnGrp);
        latestBtn.addChangeListener(listener);
        toolBar.add(latestBtn);

        customBtn = uif.createRadioButton("ce.excl.custom", btnGrp);
        customBtn.addChangeListener(listener);
        toolBar.add(customBtn);
    }

    ExcludeListParameters excludeListParameters;
    MutableExcludeListParameters mutableExcludeListParameters;

    private JToolBar toolBar;
    private ButtonGroup btnGrp;
    private JRadioButton customBtn;
    private JRadioButton initialBtn;
    private JRadioButton latestBtn;
    private JRadioButton noneBtn;

    private JPanel body;
    private JPanel blankPanel;
    private CustomPanel customPanel;
    private InitialPanel initialPanel;
    private LatestPanel latestPanel;

    private Listener listener = new Listener();

    private class Listener implements ChangeListener {
        public void stateChanged(ChangeEvent e) {
            Component comp;
            if (customBtn.isSelected())
                comp = customPanel;
            else if (initialBtn.isSelected())
                comp = initialPanel;
            else if (latestBtn.isSelected())
                comp = latestPanel;
            else
                comp = blankPanel;

            ((CardLayout)(body.getLayout())).show(body, comp.getName());
        }
    }

    private class CustomPanel extends JPanel {
        CustomPanel() {
            super(new GridBagLayout());
            setName("custom");
            GridBagConstraints c = new GridBagConstraints();

            JLabel filesLabel = uif.createLabel("ce.excl.custom.files", true);
            c.insets.top = 5;
            c.insets.bottom = 5;
            c.insets.left = 5;
            add(filesLabel, c);

            FileChooser chooser = new FileChooser(true);
            chooser.addChoosableExtension(".jtx",
                                          uif.getI18NString("ce.excl.jtxfiles"));
            // more configure ...
            filesField = new EditableFileList(chooser);
            filesField.setDuplicatesAllowed(false);
            c.fill = GridBagConstraints.HORIZONTAL;
            c.gridwidth = GridBagConstraints.REMAINDER;
            c.insets.right = 5;
            c.weightx = 1;
            c.weighty = 1;
            filesLabel.setLabelFor(filesField);
            add(filesField, c);
        }

        public void setEnabled(boolean b) {
            filesField.setEnabled(b);
        }

        void clear() {
            filesField.clear();
        }

        boolean isOKToClose() {
            File tsr = config.getTestSuite().getRoot();
            File[] files = filesField.getFiles();
            if (files.length == 0) {
                uif.showError("ce.excl.custom.noFiles");
                return false;
            }
            for (int i = 0; i < files.length; i++) {
                File file = files[i];
                File absFile = (file.isAbsolute() ? file
                                : new File(tsr, file.getPath()));
                if (!absFile.exists()) {
                    uif.showError("ce.excl.custom.cantFindFile", file);
                    return false;
                }
                if (!(absFile.isFile() && absFile.canRead())) {
                    uif.showError("ce.excl.custom.badFile", file);
                    return false;
                }
            }
            return true;
        }

        void load() {
            File[] files = mutableExcludeListParameters.getCustomExcludeFiles();
            filesField.setFiles(files);
        }

        void save() {
            File[] files = filesField.getFiles();
            mutableExcludeListParameters.setCustomExcludeFiles(files);
        }

        private EditableFileList filesField;
    }

    private class InitialPanel extends JPanel {
        InitialPanel() {
            super(new GridBagLayout());
            setName("initial");
            GridBagConstraints c = new GridBagConstraints();

            JLabel fileLabel = uif.createLabel("ce.excl.initial.file", true);
            c.anchor = GridBagConstraints.NORTH;
            c.insets.top = 20;
            c.insets.bottom = 5;
            c.insets.left = 5;
            c.insets.right = 5;
            c.weighty = 1;
            add(fileLabel, c);

            fileArea = uif.createTextArea("ce.excl.initial.file");
            fileArea.setMinimumSize(new Dimension(100, 10));
            fileArea.setEditable(false);
            fileArea.setOpaque(false);
            fileArea.setLineWrap(true);
            fileArea.setBorder(null);
            c.fill = GridBagConstraints.BOTH;
            c.weightx = 1;
            fileLabel.setLabelFor(fileArea);
            add(fileArea, c);
        }

        boolean isOKToClose() {
            if (initialFile == null) {
                uif.showError("ce.excl.initial.noFile");
                return false;
            }
            else if (!initialFile.exists()) {
                uif.showError("ce.excl.initial.cantFindFile", initialFile);
                return false;
            }
            else if (!(initialFile.isFile() && initialFile.canRead())) {
                uif.showError("ce.excl.initial.cantReadFile", initialFile);
                return false;
            }
            else
                return true;
        }

        void load(File initialFile) {
            this.initialFile = initialFile;
            if (initialFile == null)
                fileArea.setText("");
            else
                fileArea.setText(initialFile.getPath());
        }

        private JTextArea fileArea;
        private File initialFile;
    }

    private class LatestPanel extends JPanel
        implements ActionListener, ChangeListener
    {
        LatestPanel() {
            super(new BorderLayout());
            setName("latest");

            // ----- head -----
            JPanel head = uif.createPanel("ce.excl.latest.head",
                                new GridBagLayout(),
                                false);
            head.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

            GridBagConstraints lc = new GridBagConstraints();
            lc.anchor = GridBagConstraints.NORTHWEST;
            lc.insets.right = 5;

            GridBagConstraints fc = new GridBagConstraints();
            fc.fill = GridBagConstraints.HORIZONTAL;
            fc.weightx = 1;
            fc.gridwidth = GridBagConstraints.REMAINDER;

            JLabel urlLabel = uif.createLabel("ce.excl.latest.url", true);
            head.add(urlLabel, lc);

            urlField = uif.createTextArea("ce.excl.latest.url");
            urlField.setEditable(false);
            urlField.setLineWrap(true);
            urlField.setOpaque(false);
            urlField.setBorder(null);
            urlField.setMinimumSize(new Dimension(100, 10));
            urlField.setSize(new Dimension(2 * uif.getDotsPerInch(), Integer.MAX_VALUE));
            urlLabel.setLabelFor(urlField);
            head.add(urlField, fc);

            JLabel dateLabel = uif.createLabel("ce.excl.latest.date", true);
            head.add(dateLabel, lc);

            dateField = uif.createOutputField("ce.excl.latest.date", dateLabel);
            dateField.setBorder(null);
            dateLabel.setLabelFor(dateField);
            head.add(dateField, fc);
            add(head, BorderLayout.NORTH);

            // ----- body -----
            JPanel body = uif.createPanel("ce.excl.latest.body",
                                        new GridBagLayout(),
                                        false);
            body.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));

            GridBagConstraints c = new GridBagConstraints();

            autoCheck = uif.createCheckBox("ce.excl.latest.auto");
            autoCheck.addChangeListener(this);
            c.weightx = 1;
            c.gridwidth = GridBagConstraints.REMAINDER;
            c.anchor = GridBagConstraints.WEST;
            body.add(autoCheck, c);

            btnGrp = new ButtonGroup();

            c = new GridBagConstraints();
            c.insets.left = 17;
            daysButton = uif.createRadioButton("ce.excl.latest.everyXDays", btnGrp);
            daysButton.addChangeListener(this);
            body.add(daysButton, c);

            daysField = uif.createInputField("ce.excl.latest.days", 3);
            daysField.setText("7");
            c.insets.left = 0;
            c.insets.right = 5;
            body.add(daysField, c);

            daysLabel = uif.createHeading("ce.excl.latest.days");
            daysLabel.setFont(daysButton.getFont());
            daysLabel.setForeground(daysButton.getForeground());
            body.add(daysLabel, c);

            runButton = uif.createRadioButton("ce.excl.latest.everyRun", btnGrp);
            runButton.addChangeListener(this);
            c.insets.left = 20;
            c.anchor = GridBagConstraints.WEST;
            c.weightx = 1;
            body.add(runButton, c);

            add(body, BorderLayout.CENTER);

            // ----- foot -----
            JPanel foot = uif.createPanel("ce.excl.latest.foot",
                                        new GridBagLayout(),
                                        false);
            foot.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
            c = new GridBagConstraints();
            c.anchor = GridBagConstraints.EAST;
            c.weightx = 1;
            nowButton = uif.createButton("ce.excl.latest.now", this);
            foot.add(nowButton, c);

            add(foot, BorderLayout.SOUTH);
        }

        boolean isOKToClose() {
            if (autoCheck.isSelected() && daysButton.isSelected()) {
                String dt = daysField.getText();
                if (dt == null || dt.length() ==0) {
                    uif.showError("ce.excl.latest.noDays");
                    return false;
                }
                try {
                    int d = Integer.parseInt(dt);
                    if (d <= 0) {
                        uif.showError("ce.excl.latest.badDays");
                        return false;
                    }
                }
                catch (NumberFormatException e) {
                    uif.showError("ce.excl.latest.badDays");
                    return false;
                }
            }

            File l = config.getWorkDirectory().getSystemFile("latest.jtx");
            if (!l.exists() && !autoCheck.isSelected()) {
                uif.showError("ce.excl.latest.noFile");
                return false;
            }

            return true;
        }

        void load(URL latestURL, File latestFile) {
            if (latestURL == null)
                urlField.setText("");
            else
                urlField.setText(latestURL.toString());

            this.latestFile = latestFile;
            updateDateField();

            boolean ac = mutableExcludeListParameters.isLatestExcludeAutoCheckEnabled();
            autoCheck.setSelected(ac);

            int acm = mutableExcludeListParameters.getLatestExcludeAutoCheckMode();
            if (acm == MutableExcludeListParameters.CHECK_EVERY_X_DAYS)
                daysButton.setSelected(true);
            else
                runButton.setSelected(true);

            int days = mutableExcludeListParameters.getLatestExcludeAutoCheckInterval();
            if (days < 0)
                daysField.setText("");
            else
                daysField.setText(String.valueOf(days));
        }

        void save() {
            boolean ac = autoCheck.isSelected();
            mutableExcludeListParameters.setLatestExcludeAutoCheckEnabled(ac);

            int acm = (daysButton.isSelected()
                       ? MutableExcludeListParameters.CHECK_EVERY_X_DAYS
                       : MutableExcludeListParameters.CHECK_EVERY_RUN);
            mutableExcludeListParameters.setLatestExcludeAutoCheckMode(acm);

            try {
                String ds = daysField.getText();
                if (ds.length() > 0) {
                    int days = Integer.parseInt(ds);
                    mutableExcludeListParameters.setLatestExcludeAutoCheckInterval(days);
                }
            }
            catch (NumberFormatException e) {
                mutableExcludeListParameters.setLatestExcludeAutoCheckInterval(Integer.MIN_VALUE);
            }
        }

        void setCheckExcludeListListener(ActionListener l) {
            checkExcludeListListener = l;
        }

        public void actionPerformed(ActionEvent e) {
            if (checkExcludeListListener != null) {
                checkExcludeListListener.actionPerformed(e);
                updateDateField();
            }
        }


        public void stateChanged(ChangeEvent e) {
            boolean ac = autoCheck.isSelected();
            daysButton.setEnabled(ac);
            daysField.setEnabled(ac && daysButton.isSelected());
            daysLabel.setEnabled(ac);
            runButton.setEnabled(ac);
        }

        private void updateDateField() {
            long latestLastModified = latestFile.lastModified();
            if (latestLastModified <= 0)
                dateField.setText(uif.getI18NString("ce.excl.latest.dateNotAvailable"));
            else {
                DateFormat df = DateFormat.getDateTimeInstance();
                dateField.setText(df.format(new Date(latestLastModified)));
            }
        }

        private JTextArea urlField;
        private JTextField dateField;
        private JCheckBox autoCheck;
        private ButtonGroup btnGrp;
        private JRadioButton daysButton;
        private JTextField daysField;
        private JTextField daysLabel;
        private JRadioButton runButton;
        private JButton nowButton;

        private File latestFile;
        private ActionListener checkExcludeListListener;
    }
}
