/*
 [The "BSD licence"]
 Copyright (c) 2009 Shaoting Cai
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
 are met:
 1. Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
 2. Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
 3. The name of the author may not be used to endorse or promote products
    derived from this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.antlr.gunit.swingui;

import org.antlr.gunit.swingui.model.*;
import org.antlr.gunit.swingui.ImageFactory;
import java.awt.*;
import java.awt.event.*;
import java.util.HashMap;
import javax.swing.*;
import javax.swing.event.*;

/**
 *
 * @author scai
 */
public class TestCaseEditController implements IController {

    private JPanel view = new JPanel();

    private JScrollPane scroll;
    private JPanel paneDetail;
    private AbstractEditorPane paneDetailInput, paneDetailOutput;
    private JToolBar toolbar;
    private JList listCases;
    private ListModel listModel ;

    public ActionListener onTestCaseNumberChange;

    /* EDITORS */
    private InputFileEditor editInputFile;
    private InputStringEditor editInputString;
    private InputMultiEditor editInputMulti;
    private OutputResultEditor editOutputResult;
    private OutputAstEditor editOutputAST;
    private OutputStdEditor editOutputStd;
    private OutputReturnEditor editOutputReturn;
    
    private JComboBox comboInputType, comboOutputType;

    /* TYPE NAME */
    private static final String IN_TYPE_STRING = "Single-line Text";
    private static final String IN_TYPE_MULTI = "Multi-line Text";
    private static final String IN_TYPE_FILE = "Disk File";
    private static final String OUT_TYPE_BOOL = "OK or Fail";
    private static final String OUT_TYPE_AST = "AST";
    private static final String OUT_TYPE_STD = "Standard Output";
    private static final String OUT_TYPE_RET = "Return Value";

    private static final String DEFAULT_IN_SCRIPT = "";
    private static final String DEFAULT_OUT_SCRIPT = "";

    private static final Object[] INPUT_TYPE =  {
        IN_TYPE_STRING, IN_TYPE_MULTI, IN_TYPE_FILE
    };

    private static final Object[] OUTPUT_TYPE = {
        OUT_TYPE_BOOL, OUT_TYPE_AST, OUT_TYPE_STD, OUT_TYPE_RET
    };

    /* SIZE */
    private static final int TEST_CASE_DETAIL_WIDTH = 300;
    private static final int TEST_EDITOR_WIDTH = 280;
    private static final int TEST_CASE_DETAIL_HEIGHT = 250;
    private static final int TEST_EDITOR_HEIGHT = 120;

    /* MODEL */
    private Rule currentRule = null;
    private TestCase currentTestCase = null;

    /* END OF MODEL*/

    private static final HashMap<Class, String> TypeNameTable;
    static {
        TypeNameTable = new HashMap<Class, String> ();
        TypeNameTable.put(TestCaseInputString.class, IN_TYPE_STRING);
        TypeNameTable.put(TestCaseInputMultiString.class, IN_TYPE_MULTI);
        TypeNameTable.put(TestCaseInputFile.class, IN_TYPE_FILE);

        TypeNameTable.put(TestCaseOutputResult.class, OUT_TYPE_BOOL);
        TypeNameTable.put(TestCaseOutputAST.class, OUT_TYPE_AST);
        TypeNameTable.put(TestCaseOutputStdOut.class, OUT_TYPE_STD);
        TypeNameTable.put(TestCaseOutputReturn.class, OUT_TYPE_RET);
    }

    //private WorkSpaceView owner;

    public TestCaseEditController(WorkSpaceView workspace) {
        //this.owner = workspace;
        initComponents();
    }

    public TestCaseEditController() {
        initComponents();
    }

    public void OnLoadRule(Rule rule) {
        if(rule == null) throw new IllegalArgumentException("Null");
        this.currentRule = rule;
        this.currentTestCase = null;
        this.listModel = rule;
        this.listCases.setModel(this.listModel);      
    }

    public void setCurrentTestCase(TestCase testCase) {
        if(testCase == null) throw new IllegalArgumentException("Null");
        this.listCases.setSelectedValue(testCase, true);
        this.currentTestCase = testCase;
    }

    public Rule getCurrentRule() {
        return this.currentRule;
    }
    
    private void initComponents() {

        /* CASE LIST */
        listCases = new JList();
        listCases.addListSelectionListener(new TestCaseListSelectionListener());
        listCases.setCellRenderer(listRenderer);
        listCases.setOpaque(false);
        
        scroll = new JScrollPane(listCases);
        scroll.setBorder(BorderFactory.createTitledBorder(
                BorderFactory.createEmptyBorder(), "Test Cases"));
        scroll.setOpaque(false);
        scroll.setViewportBorder(BorderFactory.createEtchedBorder());

        /* CASE DETAIL */

        editInputString = new InputStringEditor();
        editInputMulti = new InputMultiEditor();
        editInputFile = new InputFileEditor();

        editOutputResult = new OutputResultEditor();
        editOutputAST = new OutputAstEditor();
        editOutputStd = new OutputStdEditor();
        editOutputReturn = new OutputReturnEditor();
        
        paneDetail = new JPanel();
        paneDetail.setBorder(BorderFactory.createEmptyBorder());
        paneDetail.setOpaque(false);

        comboInputType = new JComboBox(INPUT_TYPE);
        comboInputType.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                OnInputTestCaseTypeChanged(comboInputType.getSelectedItem());
            }
        });
        comboOutputType = new JComboBox(OUTPUT_TYPE);
        comboOutputType.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                OnOutputTestCaseTypeChanged(comboOutputType.getSelectedItem());
            }
        });
        paneDetailInput = new InputEditorPane(comboInputType);
        paneDetailOutput = new OutputEditorPane(comboOutputType);

        BoxLayout layout = new BoxLayout(paneDetail, BoxLayout.PAGE_AXIS);
        paneDetail.setLayout(layout);
        
        paneDetail.add(this.paneDetailInput);
        paneDetail.add(this.paneDetailOutput);

        /* TOOLBAR */
        toolbar = new JToolBar("Edit TestCases", JToolBar.VERTICAL);
        toolbar.setFloatable(false);
        toolbar.add(new AddTestCaseAction());
        toolbar.add(new RemoveTestCaseAction());

        /* COMPOSITE */
        view.setLayout(new BorderLayout());
        view.setBorder(BorderFactory.createEmptyBorder());
        view.setOpaque(false);
        view.add(toolbar, BorderLayout.WEST);
        view.add(scroll, BorderLayout.CENTER);
        view.add(paneDetail, BorderLayout.EAST);
    }

    private void updateInputEditor() {
        JComponent editor = null;

        if(currentTestCase != null ) {
            ITestCaseInput input = this.currentTestCase.getInput();
            if(input instanceof TestCaseInputString) {
                this.editInputString.setText(input.getScript());
                editor = this.editInputString;
                comboInputType.setSelectedItem(IN_TYPE_STRING);
            } else if(input instanceof TestCaseInputMultiString) {
                this.editInputMulti.setText(input.getScript());
                editor = this.editInputMulti.getView();
                comboInputType.setSelectedItem(IN_TYPE_MULTI);
            } else if(input instanceof TestCaseInputFile) {
                this.editInputFile.setText(input.getScript());
                editor = this.editInputFile;
                comboInputType.setSelectedItem(IN_TYPE_FILE);
            } else {
                throw new Error("Wrong type");
            }
        }
        
        paneDetailInput.setEditor(editor);
    }

    private void updateOutputEditor() {
        JComponent editor = null;
        
        if(currentTestCase != null) {
            
            ITestCaseOutput output = this.currentTestCase.getOutput();

            if(output instanceof TestCaseOutputAST) {

                this.editOutputAST.setText(output.getScript());
                editor = this.editOutputAST.getView();
                comboOutputType.setSelectedItem(OUT_TYPE_AST);

            } else if(output instanceof TestCaseOutputResult) {

                this.editOutputResult.setValue(output.getScript());
                editor = this.editOutputResult;
                comboOutputType.setSelectedItem(OUT_TYPE_BOOL);

            } else if(output instanceof TestCaseOutputStdOut) {

                this.editOutputStd.setText(output.getScript());
                editor = this.editOutputStd.getView();
                comboOutputType.setSelectedItem(OUT_TYPE_STD);

            } else if(output instanceof TestCaseOutputReturn) {

                this.editOutputReturn.setText(output.getScript());
                editor = this.editOutputReturn.getView();
                comboOutputType.setSelectedItem(OUT_TYPE_RET);

            } else {

                throw new Error("Wrong type");
                
            }

        }
        this.paneDetailOutput.setEditor(editor);
    }

    private void OnInputTestCaseTypeChanged(Object inputTypeStr) {
        if(this.currentTestCase != null) {
            ITestCaseInput input ;
            if(inputTypeStr == IN_TYPE_STRING) {
                input = new TestCaseInputString(DEFAULT_IN_SCRIPT);
            } else if(inputTypeStr == IN_TYPE_MULTI) {
                input = new TestCaseInputMultiString(DEFAULT_IN_SCRIPT);
            } else if(inputTypeStr == IN_TYPE_FILE) {
                input = new TestCaseInputFile(DEFAULT_IN_SCRIPT);
            } else {
                throw new Error("Wrong Type");
            }

            if(input.getClass().equals(this.currentTestCase.getInput().getClass()))
                return ;

            this.currentTestCase.setInput(input);
        }
        this.updateInputEditor();
    }

    private void OnOutputTestCaseTypeChanged(Object outputTypeStr) {
        if(this.currentTestCase != null) {

            ITestCaseOutput output ;
            if(outputTypeStr == OUT_TYPE_AST) {
                output = new TestCaseOutputAST(DEFAULT_OUT_SCRIPT);
            } else if(outputTypeStr == OUT_TYPE_BOOL) {
                output = new TestCaseOutputResult(false);
            } else if(outputTypeStr == OUT_TYPE_STD) {
                output = new TestCaseOutputStdOut(DEFAULT_OUT_SCRIPT);
            } else if(outputTypeStr == OUT_TYPE_RET) {
                output = new TestCaseOutputReturn(DEFAULT_OUT_SCRIPT);
            } else {
                throw new Error("Wrong Type");
            }

            if(output.getClass().equals(this.currentTestCase.getOutput().getClass()))
                return ;

            this.currentTestCase.setOutput(output);
        }
        this.updateOutputEditor();
    }


    private void OnTestCaseSelected(TestCase testCase) {
        //if(testCase == null) throw new RuntimeException("Null TestCase");
        this.currentTestCase = testCase;
        updateInputEditor();
        updateOutputEditor();

    }

    private void OnAddTestCase() {
        if(currentRule == null) return;
        
        final TestCase newCase = new TestCase(
                new TestCaseInputString(""),
                new TestCaseOutputResult(true));
        this.currentRule.addTestCase(newCase);
        setCurrentTestCase(newCase);

        this.listCases.setSelectedValue(newCase, true);
        this.listCases.updateUI();
        this.OnTestCaseSelected(newCase);
        this.onTestCaseNumberChange.actionPerformed(null);
    }

    private void OnRemoveTestCase() {
        if(currentTestCase == null) return;
        currentRule.removeElement(currentTestCase);
        listCases.updateUI();

        final TestCase nextActiveCase = listCases.isSelectionEmpty() ?
            null : (TestCase) listCases.getSelectedValue() ;
        OnTestCaseSelected(nextActiveCase);
        this.onTestCaseNumberChange.actionPerformed(null);
    }

    public Object getModel() {
        return currentRule;
    }

    public Component getView() {
        return view;
    }

    /* EDITOR CONTAINER */

    abstract public class AbstractEditorPane extends JPanel {

        private JComboBox combo;
        private JComponent editor;
        private String title;
        private JLabel placeHolder = new JLabel();

        public AbstractEditorPane(JComboBox comboBox, String title) {
            this.combo = comboBox;
            this.editor = placeHolder;
            this.title = title;
            this.initComponents();
        }

        private void initComponents() {
            placeHolder.setPreferredSize(new Dimension(
                    TEST_CASE_DETAIL_WIDTH, TEST_CASE_DETAIL_HEIGHT));
            this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
            this.add(combo, BorderLayout.NORTH);
            this.add(editor, BorderLayout.CENTER);
            this.setOpaque(false);
            this.setBorder(BorderFactory.createTitledBorder(title));
            this.setPreferredSize(new Dimension(
                    TEST_CASE_DETAIL_WIDTH, TEST_CASE_DETAIL_HEIGHT));
        }

        public void setEditor(JComponent newEditor) {
            if(newEditor == null) newEditor = placeHolder;
            this.remove(editor);
            this.add(newEditor);
            this.editor = newEditor;
            this.updateUI();
        }
    }

    public class InputEditorPane extends AbstractEditorPane {
        public InputEditorPane(JComboBox comboBox) {
            super(comboBox, "Input");
        }
    }

    public class OutputEditorPane extends AbstractEditorPane {
        public OutputEditorPane(JComboBox comboBox) {
            super(comboBox, "Output");
        }
    }

    /* INPUT EDITORS */

    public class InputStringEditor extends JTextField implements CaretListener {
        public InputStringEditor() {
            super();

            this.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
            this.addCaretListener(this);
        }

        public void caretUpdate(CaretEvent arg0) {
            currentTestCase.getInput().setScript(getText());
            listCases.updateUI();
        }
    }

    public class InputMultiEditor implements CaretListener {
        private JTextArea textArea = new JTextArea(20, 30);
        private JScrollPane scroll = new JScrollPane(textArea,
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

        public InputMultiEditor() {
            super();
            scroll.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
            textArea.addCaretListener(this);
        }

        public void caretUpdate(CaretEvent arg0) {
            currentTestCase.getInput().setScript(getText());
            listCases.updateUI();
        }

        public String getText() {
            return textArea.getText();
        }

        public void setText(String text) {
            textArea.setText(text);
        }

        public JComponent getView() {
            return scroll;
        }
    }

    public class InputFileEditor extends InputStringEditor {};

    public class OutputResultEditor extends JPanel implements ActionListener {
        
        private JToggleButton tbFail, tbOk;

        public OutputResultEditor() {
            super();

            tbFail = new JToggleButton("Fail");
            tbOk = new JToggleButton("OK");
            ButtonGroup group = new ButtonGroup();
            group.add(tbFail);
            group.add(tbOk);

            this.add(tbFail);
            this.add(tbOk);

            this.tbFail.addActionListener(this);
            this.tbOk.addActionListener(this);

            this.setPreferredSize(
                    new Dimension(TEST_EDITOR_WIDTH, 100));
        }

        public void actionPerformed(ActionEvent e) {
            TestCaseOutputResult output =
                    (TestCaseOutputResult) currentTestCase.getOutput();

            if(e.getSource() == tbFail) {
                output.setScript(false);
            } else {
                output.setScript(true);
            }

            listCases.updateUI();
        }

        public void setValue(String value) {
            if(TestCaseOutputResult.OK.equals(value)) {
                this.tbOk.setSelected(true);
            } else {
                this.tbFail.setSelected(true);
            }
        }
    }
    

    public class OutputAstEditor implements CaretListener {
        private JTextArea textArea = new JTextArea(20, 30);
        private JScrollPane scroll = new JScrollPane(textArea,
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

        public OutputAstEditor() {
            super();
            scroll.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
            textArea.addCaretListener(this);
        }

        public void caretUpdate(CaretEvent arg0) {
            currentTestCase.getOutput().setScript(getText());
            listCases.updateUI();
        }

        public void setText(String text) {
            this.textArea.setText(text);
        }

        public String getText() {
            return this.textArea.getText();
        }

        public JScrollPane getView() {
            return this.scroll;
        }
    }


    public class OutputStdEditor extends OutputAstEditor {}
    public class OutputReturnEditor extends OutputAstEditor {}

    /* EVENT HANDLERS */

    private class TestCaseListSelectionListener implements ListSelectionListener {

        public void valueChanged(ListSelectionEvent e) {
            
            if(e.getValueIsAdjusting()) return;
            final JList list = (JList) e.getSource();
            final TestCase value = (TestCase) list.getSelectedValue();
            if(value != null) OnTestCaseSelected(value);
            
        }

    }

    /* ACTIONS */

    private class AddTestCaseAction extends AbstractAction {
        public AddTestCaseAction() {
            super("Add", ImageFactory.getSingleton().ADD);
            putValue(SHORT_DESCRIPTION, "Add a gUnit test case.");
        }
        public void actionPerformed(ActionEvent e) {
            OnAddTestCase();
        }
    }

    private class RemoveTestCaseAction extends AbstractAction {
        public RemoveTestCaseAction() {
            super("Remove", ImageFactory.getSingleton().DELETE);
            putValue(SHORT_DESCRIPTION, "Remove a gUnit test case.");
        }
        public void actionPerformed(ActionEvent e) {
            OnRemoveTestCase();
        }
    }

    /* CELL RENDERERS */

    private static TestCaseListRenderer listRenderer
            = new TestCaseListRenderer();

    private static class TestCaseListRenderer implements ListCellRenderer {

        private static Font IN_FONT = new Font("mono", Font.PLAIN, 12);
        private static Font OUT_FONT = new Font("default", Font.BOLD, 12);

        public static String clamp(String text, int len) {
            if(text.length() > len) {
                return text.substring(0, len - 3).concat("...");
            } else {
                return text;
            }
        }

        public static String clampAtNewLine(String text) {
            int pos = text.indexOf('\n');
            if(pos >= 0) {
                return text.substring(0, pos).concat("...");
            } else {
                return text;
            }
        }

        public Component getListCellRendererComponent(
                JList list, Object value, int index,
                boolean isSelected, boolean hasFocus) {

            final JPanel pane = new JPanel();
            
            if (value instanceof TestCase) {
                final TestCase item = (TestCase) value;

                // create components
                final JLabel labIn = new JLabel(
                        clamp(clampAtNewLine(item.getInput().getScript()), 18));
                final JLabel labOut = new JLabel(
                        clamp(clampAtNewLine(item.getOutput().getScript()), 18));
                labOut.setFont(OUT_FONT);
                labIn.setFont(IN_FONT);

                labIn.setIcon(item.getInput() instanceof TestCaseInputFile ?
                    ImageFactory.getSingleton().FILE16 :
                    ImageFactory.getSingleton().EDIT16);

                pane.setBorder(BorderFactory.createEtchedBorder());
                pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
                pane.add(labIn);
                pane.add(labOut);
                pane.setBackground(isSelected ? Color.LIGHT_GRAY : Color.WHITE);
            } 

            return pane;
        }
    }

}
