package edu.uoregon.tau.paraprof.other;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.io.File;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Vector;

import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

import junit.extensions.jfcunit.JFCTestCase;
import junit.extensions.jfcunit.JFCTestHelper;
import junit.extensions.jfcunit.TestHelper;
import junit.extensions.jfcunit.finder.ComponentFinder;
import junit.extensions.jfcunit.finder.JMenuItemFinder;
import junit.extensions.jfcunit.finder.NamedComponentFinder;
import junit.framework.Assert;
import edu.uoregon.tau.paraprof.CallGraphWindow;
import edu.uoregon.tau.paraprof.DerivedMetrics;
import edu.uoregon.tau.paraprof.FunctionBarChartWindow;
import edu.uoregon.tau.paraprof.HistogramWindow;
import edu.uoregon.tau.paraprof.ParaProf;
import edu.uoregon.tau.paraprof.ParaProfApplication;
import edu.uoregon.tau.paraprof.ParaProfExperiment;
import edu.uoregon.tau.paraprof.ParaProfMetric;
import edu.uoregon.tau.paraprof.ParaProfTrial;
import edu.uoregon.tau.paraprof.StatWindow;
import edu.uoregon.tau.paraprof.treetable.TreeTableWindow;
import edu.uoregon.tau.perfdmf.Application;
import edu.uoregon.tau.perfdmf.DBDataSource;
import edu.uoregon.tau.perfdmf.DatabaseAPI;
import edu.uoregon.tau.perfdmf.Experiment;
import edu.uoregon.tau.perfdmf.Function;
import edu.uoregon.tau.perfdmf.taudb.TAUdbDatabaseAPI;
import edu.uoregon.tau.perfdmf.Trial;

public class JUnitParaProf extends JFCTestCase {

    private Vector<ParaProfTrial> trials = new Vector<ParaProfTrial>();

    public void wildDerivedMetrics(ParaProfTrial ppTrial) {

        //ParaProfManagerWindow paraProfManager = ParaProf.paraProfManager;

        ParaProfMetric ppMetric = DerivedMetrics.applyOperation(ppTrial.getMetric(0),
                ppTrial.getMetric(ppTrial.getNumberOfMetrics() - 1), "Divide");

        Assert.assertNotNull(ppMetric);
        ppMetric = DerivedMetrics.applyOperation(ppTrial.getMetric(1), ppTrial.getMetric(ppTrial.getNumberOfMetrics() - 1), "Add");
        Assert.assertNotNull(ppMetric);

        ppMetric = DerivedMetrics.applyOperation(ppTrial.getMetric(2), ppTrial.getMetric(ppTrial.getNumberOfMetrics() - 1),
                "Subtract");
        Assert.assertNotNull(ppMetric);

        ppMetric = DerivedMetrics.applyOperation(ppTrial.getMetric(3), ppTrial.getMetric(ppTrial.getNumberOfMetrics() - 1),
                "Multiply");
        Assert.assertNotNull(ppMetric);

        ppMetric = DerivedMetrics.applyOperation(ppTrial.getMetric(4), "val 10", "Divide");
        Assert.assertNotNull(ppMetric);
        ppMetric = DerivedMetrics.applyOperation(ppTrial.getMetric(5), "val 256", "Add");
        Assert.assertNotNull(ppMetric);
        ppMetric = DerivedMetrics.applyOperation(ppTrial.getMetric(6), "val 8.5", "Subtract");
        Assert.assertNotNull(ppMetric);
        ppMetric = DerivedMetrics.applyOperation(ppTrial.getMetric(7), "val 42.12", "Multiply");
        Assert.assertNotNull(ppMetric);

        //            java.lang.Thread.sleep(5000000);

    }

    public ParaProfTrial loadTrial(File files[], int type) {
        ParaProfApplication application = ParaProf.applicationManager.addApplication();
        application.setName("New Application");

        ParaProfExperiment experiment = application.addExperiment();

        ParaProf.paraProfManagerWindow.addTrial(application, experiment, files, type, false, false);

        Vector<ParaProfTrial> trials = experiment.getTrials();

        ParaProfTrial ppTrial = trials.get(0);

        while (ppTrial.loading()) {
            sleep(500);
        }

        return ppTrial;
    }

    private void sleep(int msec) {
        try {
            java.lang.Thread.sleep(msec);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void checkHistogram(int limit) {
        System.out.println("Testing Histogram Window");

        for (int i = 0; i < trials.size(); i++) {
            int count = limit;
            ParaProfTrial ppTrial = trials.get(i);
            System.out.println("Trial:" + ppTrial.getName());

            for (Iterator<Function> it = ppTrial.getDataSource().getFunctionIterator(); it.hasNext() && count-- != 0;) {

                Function f = (Function) it.next();
                HistogramWindow hw = new HistogramWindow(ppTrial, f, null);
                hw.setVisible(true);

                for (int n = 1; n <= 100; n += 5) {
                    hw.setNumBins(n);
                    sleep(5);
                }
                //sleep(1);
                hw.closeThisWindow();
            }
        }

    }

    public void checkHistogram(ParaProfTrial ppTrial, Function f) {

        HistogramWindow hw = new HistogramWindow(ppTrial, f, null);
        hw.setVisible(true);

        for (int n = 1; n <= 100; n += 5) {
            hw.setNumBins(n);
            sleep(5);
        }
        //sleep(1);
        hw.closeThisWindow();
    }

    public void checkThreadWindow(ParaProfTrial ppTrial, edu.uoregon.tau.perfdmf.Thread thread) {

        FunctionBarChartWindow tw = new FunctionBarChartWindow(ppTrial, thread, null, null);
        tw.setVisible(true);

        sleep(500);
        tw.closeThisWindow();
    }

    public void checkTreeTable(ParaProfTrial ppTrial, edu.uoregon.tau.perfdmf.Thread thread) {

        TreeTableWindow tw = new TreeTableWindow(ppTrial, thread, null);
        tw.setVisible(true);

        sleep(500);
        tw.closeThisWindow();
    }

    public void checkStatWindow(ParaProfTrial ppTrial, edu.uoregon.tau.perfdmf.Thread thread, boolean userEvent) {

        StatWindow w = new StatWindow(ppTrial, thread, userEvent, null, null);
        w.setVisible(true);

        sleep(500);
        w.closeThisWindow();
    }

    public void checkCallGraphWindow(ParaProfTrial ppTrial, edu.uoregon.tau.perfdmf.Thread thread) {

        CallGraphWindow cgw = new CallGraphWindow(ppTrial, thread, null);
        cgw.setVisible(true);

        sleep(500);
        cgw.closeThisWindow();
    }

    public ActionEvent createMenuAction(String s) {
        JMenuItem jMenuItem = new JMenuItem(s);
        ActionEvent evt = new ActionEvent(jMenuItem, 0, s);
        return evt;
    }

    JFCTestHelper helper = new JFCTestHelper();

    @SuppressWarnings("deprecation")
	private Component getMenuItem(JMenu menu, String menuItemName) throws Exception {
        Component comp = TestHelper.findComponent(new JMenuItemFinder(menuItemName), menu.getPopupMenu(), 0);
        assertNotNull("Could not find menu item: " + menuItemName, comp);
        return comp;
    }

    public void checkFunctionWindow(ParaProfTrial ppTrial, Function f) throws Exception {

        FunctionBarChartWindow fw = new FunctionBarChartWindow(ppTrial, f, null);
        fw.setVisible(true);
        //sleep(200000);

        ComponentFinder crapFinder = new ComponentFinder(JMenuBar.class);

        JMenuBar jMenuBar = (JMenuBar) crapFinder.find(fw, 0);

        //NamedComponentFinder menuFinder = 
        	new NamedComponentFinder(JMenu.class, "Options");

        //JMenu optionsMenu = (JMenu) menuFinder.find(jMenuBar.getRootPane(), 0);

        JMenu optionsMenu = jMenuBar.getMenu(1);

        //JMenuItemFinder finder = new JMenuItemFinder("Sort By N,C,T");
        //JCheckBoxMenuItem sortByNCT = (JCheckBoxMenuItem) finder.find(fw, 0);

        JCheckBoxMenuItem sortByNCT = (JCheckBoxMenuItem) getMenuItem(optionsMenu, "Sort By N,C,T");
        JCheckBoxMenuItem descending = (JCheckBoxMenuItem) getMenuItem(optionsMenu, "Descending Order");
        JCheckBoxMenuItem percent = (JCheckBoxMenuItem) getMenuItem(optionsMenu, "Show Values as Percent");

        int amount = 50;

        sleep(amount);

        sortByNCT.doClick();
        sleep(amount);
        descending.doClick();
        sleep(amount);
        percent.doClick();
        sleep(amount);
        //
        //        fw.actionPerformed(createMenuAction("Inclusive"));
        //        sleep(amount);
        //        fw.actionPerformed(createMenuAction("Show Values as Percent"));
        //        sleep(amount);
        //        sortByNCT.setSelected(true);
        //        fw.actionPerformed(createMenuAction("Sort By N,C,T"));
        //        sleep(amount);
        //        fw.actionPerformed(createMenuAction("Descending Order"));
        //        sleep(amount);
        //
        //        fw.actionPerformed(createMenuAction("Number of Calls"));
        //        sleep(amount);
        //        sortByNCT.setSelected(false);
        //        fw.actionPerformed(createMenuAction("Sort By N,C,T"));
        //        sleep(amount);
        //        fw.actionPerformed(createMenuAction("Descending Order"));
        //        sleep(amount);
        //
        //        fw.actionPerformed(createMenuAction("Number of Subroutines"));
        //        sleep(amount);
        //        sortByNCT.setSelected(true);
        //        fw.actionPerformed(createMenuAction("Sort By N,C,T"));
        //        sleep(amount);
        //        fw.actionPerformed(createMenuAction("Descending Order"));
        //        sleep(amount);
        //
        //        fw.actionPerformed(createMenuAction("Inclusive Per Call"));
        //        sleep(amount);
        //        sortByNCT.setSelected(false);
        //        fw.actionPerformed(createMenuAction("Sort By N,C,T"));
        //        sleep(amount);
        //        fw.actionPerformed(createMenuAction("Descending Order"));
        //        sleep(amount);

        //sleep(200000);

        fw.closeThisWindow();

    }

    public void checkDerivedMetrics() {
        System.out.println("Testing Derived Metrics");

        for (int i = 0; i < trials.size(); i++) {

            ParaProfTrial ppTrial = trials.get(i);
            System.out.println("Trial:" + ppTrial.getName());

            wildDerivedMetrics(ppTrial);

        }

        //sleep(5000000);
    }

    public void testEverything() throws Exception {

        boolean doDatabase = false;

        System.out.println("---Setting up ParaProf---");

        //final ParaProf paraProf = 
        	new ParaProf();
        ParaProf.initialize();

        //String args[] = new String[0];
        //ParaProf.main(args);

        System.out.println("---Loading Trials---");

        File[] files = new File[1];
        files[0] = new File("/home/amorris/data/tau/uintah16");
        trials.add(loadTrial(files, 0));

        files[0] = new File("/home/amorris/data/pprof/uintah/pprof.dat");
        trials.add(loadTrial(files, 1));

        files[0] = new File("/home/amorris/data/pprof/mpilieb/pprof.dat");
        trials.add(loadTrial(files, 1));

        files[0] = new File("/home/amorris/data/mpip/mpilieb-noinst.32.25678.mpiP");
        trials.add(loadTrial(files, 3));

        files[0] = new File("/home/amorris/data/dynaprof/simple.papiprobe.790616");
        trials.add(loadTrial(files, 2));

        files[0] = new File("/home/amorris/data/dynaprof/manyfunc.papiprobe.745692");
        trials.add(loadTrial(files, 2));

        files[0] = new File("/home/amorris/data/gprof/mpilieb.out");
        trials.add(loadTrial(files, 5));

        files = new File[4];
        files[0] = new File("/home/amorris/data/hpm/mpilieb/eventset1/perfhpm0000.7495902");
        files[1] = new File("/home/amorris/data/hpm/mpilieb/eventset1/perfhpm0001.1466514");
        files[2] = new File("/home/amorris/data/hpm/mpilieb/eventset1/perfhpm0002.6742226");
        files[3] = new File("/home/amorris/data/hpm/mpilieb/eventset1/perfhpm0003.5062700");
        trials.add(loadTrial(files, 4));

        files[0] = new File("/home/amorris/data/psrun/91060-tuna184.31362.xml");
        files[1] = new File("/home/amorris/data/psrun/91060-tuna184.31363.xml");
        files[2] = new File("/home/amorris/data/psrun/91060-tuna184.31530.xml");
        files[3] = new File("/home/amorris/data/psrun/91060-tuna184.31558.xml");
        trials.add(loadTrial(files, 6));

        checkDerivedMetrics();

        if (doDatabase) {
            System.out.println("---Checking the database---");
            DatabaseAPI dbApi = new DatabaseAPI();

            dbApi.initialize(ParaProf.preferences.getDatabaseConfigurationFile(), false);
			if (dbApi.db().getSchemaVersion() > 0) {
				// copy the DatabaseAPI object data into a new TAUdbDatabaseAPI object
				dbApi = new TAUdbDatabaseAPI(dbApi);
			}

            dbApi.getApplicationList();
            ListIterator<Application> apps = dbApi.getApplicationList().listIterator();

            while (apps.hasNext()) {
                Application app = (Application) apps.next();
                dbApi.setApplication(app);
                for (Iterator<Experiment> exps = dbApi.getExperimentList().listIterator(); exps.hasNext();) {
                    Experiment exp = (Experiment) exps.next();
                    dbApi.setExperiment(exp);
                    for (Iterator<Trial> trls = dbApi.getTrialList(true).listIterator(); trls.hasNext();) {
                        Trial trial = (Trial) trls.next();

                        dbApi.setTrial(trial.getID(), true);
                        DBDataSource dbDataSource = new DBDataSource(dbApi);
                        System.out.println("loading " + trial.getName());
                        dbDataSource.load();

                        ParaProfTrial ppTrial = new ParaProfTrial(trial);
                        //ppTrial.update(dbDataSource);
                        trials.add(ppTrial);
                    }
                }
            }
        }

        System.out.println("---Ready to go---");

        int limit = 2;

        try {
            for (int i = 0; i < trials.size(); i++) {
                int count = limit;
                ParaProfTrial ppTrial = trials.get(i);
                System.out.println("Trial:" + ppTrial.getName());

                for (Iterator<Function> it = ppTrial.getDataSource().getFunctionIterator(); it.hasNext() && count-- != 0;) {
                    Function f = (Function) it.next();

                    checkHistogram(ppTrial, f);
                    checkFunctionWindow(ppTrial, f);
                }

                count = limit;
                for (Iterator<edu.uoregon.tau.perfdmf.Thread> it = ppTrial.getDataSource().getAllThreads().iterator(); it.hasNext() && count-- != 0;) {
                    edu.uoregon.tau.perfdmf.Thread thread = (edu.uoregon.tau.perfdmf.Thread) it.next();

                    checkStatWindow(ppTrial, thread, false);
                    checkThreadWindow(ppTrial, thread);
                    checkTreeTable(ppTrial, thread);
                    checkStatWindow(ppTrial, thread, true);
                    checkCallGraphWindow(ppTrial, thread);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("---Finished---");

    }

    public static void main(String[] args) {}

    /*
     * @see TestCase#setUp()
     */
    protected void setUp() throws Exception {
        super.setUp();
        setHelper(new JFCTestHelper()); // Uses the AWT Event Queue.

    }

    /*
     * @see TestCase#tearDown()
     */
    protected void tearDown() throws Exception {
        super.tearDown();
    }

}
