package org.apache.felix.ipojo.junit4osgi.command;
/* 
 * 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.
 */


import junit.framework.AssertionFailedError;
import junit.framework.Test;
import junit.framework.TestResult;
import org.apache.felix.ipojo.InstanceManager;
import org.apache.felix.ipojo.junit4osgi.OSGiJunitRunner;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;

import javax.swing.*;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;

/**
 * Swing Runner for Junit4Osgi.
 *
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public class SwingRunner extends javax.swing.JFrame implements BundleListener {

    /**
     * UUID.
     */
    private static final long serialVersionUID = 1L;

    /**
     * Bundle context (to register the bundle listener).
     */
    private BundleContext m_context;

    /**
     * OSGi Junit Runner Service.
     */
    private OSGiJunitRunner m_runner;

    /**
     * State variable describing if we are executing tests.
     */
    private boolean m_running = false;


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnSearch;
    private javax.swing.JButton m_allButton;
    private javax.swing.JButton m_executeButton;
    private javax.swing.JLabel m_executedResults;
    private javax.swing.JScrollPane m_message;
    private javax.swing.JTextArea m_messageArea;
    private javax.swing.JButton m_ok;
    private javax.swing.JProgressBar m_progress;
    private javax.swing.JDialog m_resultDialog;
    private javax.swing.JScrollPane m_resultScroll;
    private javax.swing.JTable m_resultTable;
    private javax.swing.JPanel m_statusBar;
    private javax.swing.JList m_suiteList;
    private javax.swing.JScrollPane m_suiteScroll;
    private javax.swing.JTextField txtSearchTest;
    // End of variables declaration//GEN-END:variables


    public SwingRunner(BundleContext bc) {
        m_running = false;
        m_context = bc;
    }


    private void internalInitComponents() {
        initComponents();
    }



    /**
     * Start method.
     */
    public void start() {
        internalInitComponents();
        setVisible(true);
        m_resultDialog.setVisible(false);
        refreshSuites();
        m_context.addBundleListener(this);
        m_executedResults.setText(" \t No executed tests");
        m_progress.setIndeterminate(false);
        m_progress.setMaximum(100);
        m_progress.setValue(100);

        TableColumn column = null;
        for (int i = 0; i < m_resultTable.getColumnCount(); i++) {
            column = m_resultTable.getColumnModel().getColumn(i);
            if (i == 0) {
                column.setPreferredWidth(350); // first column is bigger
            } else {
                column.setPreferredWidth(50);
                column.setCellRenderer(new ResultCellRenderer());
            }
        }
    }



    /**
     * Stop method.
     */
    public void stop() {
        m_context.removeBundleListener(this);
        dispose();
    }


    /**
     * Refresh the list of available test suites.
     */
    @SuppressWarnings("unchecked")
    private void refreshSuites() {

        String textToSearch = txtSearchTest.getText();
        List<Test> tests = m_runner.getTests();

        TestListModel lm = (TestListModel) m_suiteList.getModel();
        lm.clear();

        for (Test test : tests) {
            String testName = test.toString();
            if (textToSearch != null && !textToSearch.trim().equals("")) {
                if (testName.toLowerCase().indexOf(textToSearch.toLowerCase()) != -1) {

                    lm.addTest(test);
                }
            } else {
                // found all
                lm.addTest(test);

            }
        }

        //getInstanceManager().onExit(this, "refreshSuites", null);
    }

    /**
     * This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        m_resultDialog = new javax.swing.JDialog();
        m_message = new javax.swing.JScrollPane();
        m_messageArea = new javax.swing.JTextArea();
        m_ok = new javax.swing.JButton();
        m_statusBar = new javax.swing.JPanel();
        m_progress = new javax.swing.JProgressBar();
        m_executeButton = new javax.swing.JButton();
        m_allButton = new javax.swing.JButton();
        m_suiteScroll = new javax.swing.JScrollPane();
        m_suiteList = new javax.swing.JList();
        m_resultScroll = new javax.swing.JScrollPane();
        m_resultTable = new javax.swing.JTable();
        m_executedResults = new javax.swing.JLabel();
        txtSearchTest = new javax.swing.JTextField();
        btnSearch = new javax.swing.JButton();

        m_resultDialog.setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
        m_resultDialog.setMinimumSize(new java.awt.Dimension(1024, 600));
        m_resultDialog.addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosed(java.awt.event.WindowEvent evt) {
                onDialogClosed(evt);
            }

            public void windowClosing(java.awt.event.WindowEvent evt) {
                onDialogClosed(evt);
            }
        });

        m_message.setBorder(null);
        m_message.setMinimumSize(new java.awt.Dimension(300, 202));
        m_message.setPreferredSize(new java.awt.Dimension(300, 202));

        m_messageArea.setBackground(javax.swing.UIManager.getDefaults().getColor("Panel.background"));
        m_messageArea.setColumns(20);
        m_messageArea.setEditable(false);
        m_messageArea.setLineWrap(true);
        m_messageArea.setRows(5);
        m_messageArea.setWrapStyleWord(true);
        m_messageArea.setMinimumSize(new java.awt.Dimension(300, 250));
        m_messageArea.setPreferredSize(new java.awt.Dimension(250, 200));
        m_message.setViewportView(m_messageArea);

        m_resultDialog.getContentPane().add(m_message, java.awt.BorderLayout.CENTER);

        m_ok.setText("Ok");
        m_ok.setPreferredSize(new java.awt.Dimension(120, 23));
        m_ok.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                okActionPerformed(evt);
            }
        });
        m_resultDialog.getContentPane().add(m_ok, java.awt.BorderLayout.SOUTH);

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Junit Runner");
        setMinimumSize(null);

        m_progress.setIndeterminate(true);
        m_progress.setMinimumSize(null);
        m_progress.setPreferredSize(null);

        javax.swing.GroupLayout m_statusBarLayout = new javax.swing.GroupLayout(m_statusBar);
        m_statusBar.setLayout(m_statusBarLayout);
        m_statusBarLayout.setHorizontalGroup(
                m_statusBarLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addComponent(m_progress, javax.swing.GroupLayout.DEFAULT_SIZE, 466, Short.MAX_VALUE)
        );
        m_statusBarLayout.setVerticalGroup(
                m_statusBarLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(m_statusBarLayout.createSequentialGroup()
                                .addComponent(m_progress, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        m_executeButton.setText("Execute");
        m_executeButton.setMaximumSize(new java.awt.Dimension(90, 23));
        m_executeButton.setMinimumSize(new java.awt.Dimension(90, 23));
        m_executeButton.setPreferredSize(new java.awt.Dimension(100, 23));
        m_executeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                executeButtonActionPerformed(evt);
            }
        });

        m_allButton.setText("Select All");
        m_allButton.setMaximumSize(new java.awt.Dimension(90, 23));
        m_allButton.setMinimumSize(new java.awt.Dimension(90, 23));
        m_allButton.setPreferredSize(new java.awt.Dimension(100, 23));
        m_allButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                allButtonActionPerformed(evt);
            }
        });

        m_suiteScroll.setAutoscrolls(true);

        m_suiteList.setModel(new TestListModel());
        m_suiteList.setMaximumSize(null);
        m_suiteList.setMinimumSize(null);
        m_suiteList.setPreferredSize(null);
        m_suiteScroll.setViewportView(m_suiteList);

        m_resultScroll.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

        m_resultTable.setAutoCreateRowSorter(true);
        m_resultTable.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N
        m_resultTable.setModel(new ResultTableModel());
        m_resultTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
        m_resultTable.setMaximumSize(null);
        m_resultTable.setMinimumSize(null);
        m_resultTable.setPreferredSize(null);
        m_resultTable.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                resultTableMouseClicked(evt);
            }
        });
        m_resultScroll.setViewportView(m_resultTable);

        m_executedResults.setText("aaaaaaaaaaaaaaa");
        m_executedResults.setPreferredSize(null);

        btnSearch.setText("Search");
        btnSearch.setMaximumSize(new java.awt.Dimension(90, 23));
        btnSearch.setMinimumSize(new java.awt.Dimension(90, 23));
        btnSearch.setPreferredSize(new java.awt.Dimension(100, 23));
        btnSearch.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnSearchActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(layout.createSequentialGroup()
                                .addContainerGap()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addComponent(m_resultScroll, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 598, Short.MAX_VALUE)
                                        .addGroup(layout.createSequentialGroup()
                                                .addComponent(m_statusBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                .addComponent(m_executedResults, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                                        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                                        .addComponent(txtSearchTest, javax.swing.GroupLayout.Alignment.LEADING)
                                                        .addComponent(m_suiteScroll, javax.swing.GroupLayout.DEFAULT_SIZE, 492, Short.MAX_VALUE))
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                                        .addComponent(m_executeButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                                        .addComponent(m_allButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                                        .addComponent(btnSearch, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
                                .addContainerGap())
        );
        layout.setVerticalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                        .addComponent(txtSearchTest, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addComponent(btnSearch, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addGroup(layout.createSequentialGroup()
                                                .addComponent(m_allButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                .addComponent(m_executeButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                                        .addComponent(m_suiteScroll, javax.swing.GroupLayout.DEFAULT_SIZE, 152, Short.MAX_VALUE))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(m_resultScroll, javax.swing.GroupLayout.PREFERRED_SIZE, 415, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(18, 18, 18)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addComponent(m_executedResults, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addComponent(m_statusBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents


    /**
     * Execute button action.
     *
     * @param evt : event.
     */
    private void executeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_m_executeButtonActionPerformed
        if (m_running) {
            return;
        }
        // Collect selected test.
        int[] indices = m_suiteList.getSelectedIndices();
        List<Test> list = new ArrayList<Test>(indices.length);
        TestListModel model = (TestListModel) m_suiteList.getModel();
        for (int i = 0; i < indices.length; i++) {
            list.add(model.getTestElementAt(indices[i]));
        }
        setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        executeTest(list);
    }//GEN-LAST:event_m_executeButtonActionPerformed

    /**
     * All button action.
     *
     * @param evt : event.
     */
    private void allButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_m_allButtonActionPerformed
        int max = m_suiteList.getModel().getSize();
        int[] indices = new int[max];
        for (int i = 0; i < max; i++) {
            indices[i] = i;
        }
        m_suiteList.setSelectedIndices(indices);
    }//GEN-LAST:event_m_allButtonActionPerformed

    /**
     * Listener on table click.
     *
     * @param evt : event.
     */
    private void resultTableMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_m_resultTableMouseClicked
        Point p = evt.getPoint();
        int row = m_resultTable.rowAtPoint(p);
        int col = m_resultTable.columnAtPoint(p);
        ResultTableModel model = (ResultTableModel) m_resultTable.getModel();
        String message = model.getMessage(row, col);
        if (message != null) {
            setEnabled(false);
            m_resultDialog.setTitle("Test Report");
            m_messageArea.setText(message);
            m_resultDialog.setVisible(true);
        }
    }//GEN-LAST:event_m_resultTableMouseClicked

    /**
     * Ok button action.
     *
     * @param evt : event.
     */
    private void okActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_m_okActionPerformed
        m_resultDialog.setVisible(false);
        setEnabled(true);
    }//GEN-LAST:event_m_okActionPerformed

    /**
     * Listener when the test report is closed.
     *
     * @param evt : event.
     */
    private void onDialogClosed(java.awt.event.WindowEvent evt) {
        m_resultDialog.setVisible(false);
        setEnabled(true);
    }


    private void btnSearchActionPerformed(java.awt.event.ActionEvent evt) {
        refreshSuites();

    }

    /**
     * Execute method.
     *
     * @param list : list of test to execute.
     */
    private void executeTest(final List<Test> list) {
        Runnable thread = new Runnable() {
            public void run() {
                ResultTableModel model = (ResultTableModel) m_resultTable.getModel();
                m_running = true;
                m_executeButton.setText("Running...");
                m_progress.setIndeterminate(true);
                model.clear();
                for (int i = 0; i < list.size(); i++) {
                    TestResult tr = new TestResult();
                    tr.addListener(new MyTestListener());
                    list.get(i).run(tr);
                }
                m_running = false;
                m_progress.setIndeterminate(false);
                m_progress.setMaximum(100);
                m_progress.setValue(100);
                m_executeButton.setText("Execute");
                computeExecutedTest();
                setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
            }

        };
        new Thread(thread).start();
    }

    /**
     * Compute executed tests.
     * (Status bar message)
     */
    private void computeExecutedTest() {
        ResultTableModel results = (ResultTableModel) m_resultTable.getModel();
        String m = " \t ";
        m += results.getTestCount() + " tests executed / ";
        m += results.getSucess() + " success / ";
        m += results.getFailures() + " failures / ";
        m += results.getErrors() + " errors ";
        m_executedResults.setText(m);
    }

    private class MyTestListener implements junit.framework.TestListener {
        /**
         * Table model.
         */
        ResultTableModel m_model = (ResultTableModel) m_resultTable.getModel();

        /**
         * Add an error.
         *
         * @param arg0 : test which throws an error.
         * @param arg1 : thrown exception.
         * @see junit.framework.TestListener#addError(junit.framework.Test, Throwable)
         */
        public void addError(Test arg0, Throwable arg1) {
            m_model.addTest(arg0, arg1);
            adjustScroll();
        }

        /**
         * Add a failure.
         *
         * @param arg0 : failing test.
         * @param arg1 : thrown failure.
         * @see junit.framework.TestListener#addError(junit.framework.Test, Throwable)
         */
        public void addFailure(Test arg0, AssertionFailedError arg1) {
            m_model.addTest(arg0, arg1);
            adjustScroll();
        }

        /**
         * End of a test.
         *
         * @param arg0 : test.
         * @see junit.framework.TestListener#endTest(junit.framework.Test)
         */
        public void endTest(Test arg0) {
            m_model.addTest(arg0);
            adjustScroll();
        }

        /**
         * Start of a test.
         *
         * @param arg0 : test.
         * @see junit.framework.TestListener#startTest(junit.framework.Test)
         */
        public void startTest(Test arg0) {
            // Nothing to do here.
        }

        /**
         * Adjust the scrolling bar of the result table.
         */
        private void adjustScroll() {
            JScrollBar bar = m_resultScroll.getVerticalScrollBar();
            if ((bar != null) && (bar.isVisible())) {
                bar.setValue(Integer.MAX_VALUE);
            }
        }

    }


    public void bundleChanged(BundleEvent bundleevent) {
        refreshSuites();

    }

}