/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.chemistry.opencmis.workbench.checks;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.Writer;
import java.util.List;
import java.util.Map;

import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingConstants;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;

import org.apache.chemistry.opencmis.tck.CmisTest;
import org.apache.chemistry.opencmis.tck.CmisTestGroup;
import org.apache.chemistry.opencmis.tck.CmisTestReport;
import org.apache.chemistry.opencmis.tck.CmisTestResult;
import org.apache.chemistry.opencmis.tck.report.AbstractCmisTestReport;
import org.apache.chemistry.opencmis.tck.report.HtmlReport;
import org.apache.chemistry.opencmis.tck.report.TextReport;
import org.apache.chemistry.opencmis.tck.report.XmlReport;
import org.apache.chemistry.opencmis.workbench.ClientHelper;

/**
 * Swing Report.
 */
public class SwingReport extends AbstractCmisTestReport {

    private static final Icon GROUP_ICON = new ColorIcon(Color.GRAY);
    private static final Icon TEST_ICON = new ColorIcon(Color.BLUE);
    private static final Icon STATUS_OK_ICON = new ColorIcon(Color.GREEN);
    private static final Icon STATUS_WARNING_ICON = new ColorIcon(Color.YELLOW);
    private static final Icon STATUS_FAILURE_ICON = new ColorIcon(Color.RED);
    private static final Icon OTHER_ICON = new ColorIcon(Color.LIGHT_GRAY);

    private final Frame owner;
    private final int width;
    private final int height;
    private Map<String, String> parameters;
    private List<CmisTestGroup> groups;

    public SwingReport(Frame owner, int width, int height) {
        this.owner = owner;
        this.width = width;
        this.height = height;
    }

    @Override
    public void createReport(Map<String, String> parameters, List<CmisTestGroup> groups, Writer writer) {
        this.parameters = parameters;
        this.groups = groups;
        new SwingReportDialog();
    }

    /**
     * Report dialog.
     */
    private class SwingReportDialog extends JDialog {

        private static final long serialVersionUID = 1L;

        public SwingReportDialog() {
            super(owner, "Test Report");
            createGUI();
        }

        private void createGUI() {
            setPreferredSize(new Dimension(width, height));
            setMinimumSize(new Dimension(width, height));

            setLayout(new BorderLayout());

            DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Groups");

            for (CmisTestGroup group : groups) {
                if (!group.isEnabled()) {
                    continue;
                }

                DefaultMutableTreeNode groupNode = new DefaultMutableTreeNode(group);
                rootNode.add(groupNode);
                for (CmisTest test : group.getTests()) {
                    if (!test.isEnabled()) {
                        continue;
                    }

                    DefaultMutableTreeNode testNode = new DefaultMutableTreeNode(test);
                    groupNode.add(testNode);
                    populateResultBranch(testNode, test.getResults());
                }
            }

            JTree groupTree = new JTree(rootNode);
            groupTree.setRootVisible(false);
            groupTree.setCellRenderer(new ReportTreeCellRenderer());

            for (int i = 0; i < groupTree.getRowCount(); i++) {
                groupTree.expandRow(i);
            }

            add(new JScrollPane(groupTree), BorderLayout.CENTER);

            final JPanel reportPanel = new JPanel();
            reportPanel.add(new JLabel("Open report as "));
            final JComboBox reportType = new JComboBox(new Object[] { "HTML", "Text", "XML" });
            reportPanel.add(reportType);
            final JButton reportButton = new JButton("go");
            reportPanel.add(reportButton);

            reportButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent event) {
                    try {
                        // create report
                        File tempReportFile = null;
                        CmisTestReport report = null;

                        switch (reportType.getSelectedIndex()) {
                        case 1:
                            tempReportFile = File.createTempFile("cmistck", ".txt");
                            report = new TextReport();
                            break;
                        case 2:
                            tempReportFile = File.createTempFile("cmistck", ".xml");
                            report = new XmlReport();
                            break;
                        default:
                            tempReportFile = File.createTempFile("cmistck", ".html");
                            report = new HtmlReport();
                            break;
                        }

                        tempReportFile.deleteOnExit();
                        report.createReport(parameters, groups, tempReportFile);

                        // show report
                        Desktop desktop = Desktop.getDesktop();
                        if (!desktop.isSupported(Desktop.Action.OPEN)) {
                            JOptionPane.showMessageDialog(owner, "Report: " + tempReportFile.getAbsolutePath(),
                                    "Report", JOptionPane.INFORMATION_MESSAGE);
                        } else {
                            desktop.open(tempReportFile);
                        }
                    } catch (Exception e) {
                        JOptionPane.showMessageDialog(owner, "Error: " + e.getMessage(), "Report Error",
                                JOptionPane.ERROR_MESSAGE);
                    }
                }
            });

            add(reportPanel, BorderLayout.PAGE_END);

            ClientHelper.installEscapeBinding(this, getRootPane(), true);

            setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            pack();
            setLocationRelativeTo(null);
            setVisible(true);
        }

        private void populateResultBranch(DefaultMutableTreeNode parent, List<CmisTestResult> results) {
            if (results == null) {
                return;
            }

            for (CmisTestResult result : results) {
                DefaultMutableTreeNode resultNode = new DefaultMutableTreeNode(result);
                parent.add(resultNode);
                populateResultBranch(resultNode, result.getChildren());
            }
        }

        private class ReportTreeCellRenderer extends DefaultTreeCellRenderer {

            private static final long serialVersionUID = 1L;

            public ReportTreeCellRenderer() {
            }

            public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded,
                    boolean leaf, int row, boolean hasFocus) {
                super.getTreeCellRendererComponent(tree, "", sel, expanded, leaf, row, hasFocus);

                DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;

                if (node.getUserObject() instanceof CmisTestGroup) {
                    setText(((CmisTestGroup) node.getUserObject()).getName());
                    setIcon(GROUP_ICON);
                } else if (node.getUserObject() instanceof CmisTest) {
                    setText(((CmisTest) node.getUserObject()).getName());
                    setIcon(TEST_ICON);
                } else if (node.getUserObject() instanceof CmisTestResult) {
                    CmisTestResult result = (CmisTestResult) node.getUserObject();

                    String text = "<html><b>" + result.getStatus() + ": " + result.getMessage() + "</b>";
                    if ((result.getStackTrace() != null) && (result.getStackTrace().length > 0)) {
                        text += " (" + result.getStackTrace()[0].getFileName() + ":"
                                + result.getStackTrace()[0].getLineNumber() + ")";
                    }
                    setText(text);

                    switch (result.getStatus()) {
                    case OK:
                        setIcon(STATUS_OK_ICON);
                        break;
                    case WARNING:
                        setIcon(STATUS_WARNING_ICON);
                        break;
                    case FAILURE:
                    case UNEXPECTED_EXCEPTION:
                        setIcon(STATUS_FAILURE_ICON);
                        break;
                    default:
                        setIcon(OTHER_ICON);
                    }
                } else {
                    setText(value.toString());
                    setIcon(OTHER_ICON);
                }

                setVerticalTextPosition(SwingConstants.TOP);

                return this;
            }
        }
    }

    private static class ColorIcon implements Icon {

        private final Color color;

        public ColorIcon(Color color) {
            this.color = color;
        }

        public void paintIcon(Component c, Graphics g, int x, int y) {
            g.setColor(color);
            g.fillRect(0, 0, getIconWidth(), getIconHeight());
        }

        public int getIconWidth() {
            return 8;
        }

        public int getIconHeight() {
            return 18;
        }
    }
}
