// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
 *******************************************************************************
 * Copyright (C) 2007-2011, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.dev.demo;

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.ibm.icu.dev.demo.impl.DemoApplet;
import com.ibm.icu.dev.demo.impl.DemoUtility;
import com.ibm.icu.util.VersionInfo;


/**
 * @author srl
 * Application to provide a panel of demos to launch
 */
public class Launcher extends DemoApplet {
    private static final long serialVersionUID = -8054963875776183877L;
    
    /**
     * base package of all demos
     */
    public static final String demoBase = "com.ibm.icu.dev.demo";
    /**
     * list of classes, relative to the demoBase. all must have a static void main(String[])
     */
    public static final String demoList[] = { 
        "calendar.CalendarApp",
        "charsetdet.DetectingViewer",
        "holiday.HolidayCalendarDemo",
        "rbnf.RbnfDemo",
        "translit.Demo",
    };

    public class LauncherFrame extends Frame implements ActionListener {
        private static final long serialVersionUID = -8054963875776183878L;
        
        public Button buttonList[] = new Button[demoList.length]; // one button for each demo
        public Label statusLabel;
        private DemoApplet applet;
        
        LauncherFrame(DemoApplet applet) {
            init();
            this.applet = applet;
        }
        
        public void init() {
            // close down when close is clicked.
            // TODO: this should be factored..
            addWindowListener(
                    new WindowAdapter() {
                        public void windowClosing(WindowEvent e) {
                            setVisible(false);
                            dispose();

                            if (applet != null) {
                                applet.demoClosed();
                            } else System.exit(0);
                        }
                    } );

            setBackground(DemoUtility.bgColor);
            setLayout(new BorderLayout());

            Panel topPanel = new Panel();
            topPanel.setLayout(new GridLayout(5,3));

            for(int i=0;i<buttonList.length;i++) {
                String demo = demoList[i];
                Button b = new Button(demo);
                b.addActionListener(this);
                buttonList[i]=b;
                topPanel.add(b);
            }
            add(BorderLayout.CENTER,topPanel);
            statusLabel = new Label("");
            statusLabel.setAlignment(Label.LEFT);
            String javaVersion = "";
            try { 
                javaVersion = "* Java: "+System.getProperty("java.version");
            } catch (Throwable t) {
                javaVersion = "";
            }
            add(BorderLayout.NORTH, new Label(
                   "ICU Demos * ICU version "+VersionInfo.ICU_VERSION +
                   " * https://icu.unicode.org/ "+javaVersion));
            add(BorderLayout.SOUTH,statusLabel);
            // set up an initial status.
            showStatus(buttonList.length+" demos ready. ");
        }
        
        /**
         * Change the 'status' field, and set it to black
         * @param status
         */
        void showStatus(String status) {
            statusLabel.setText(status);
            statusLabel.setForeground(Color.BLACK);
            statusLabel.setBackground(Color.WHITE);
//            statusLabel.setFont(Font.PLAIN);
            doLayout();
        }
        void showStatus(String demo, String status) {
            showStatus(demo+": "+status);
        }
        void showFailure(String status) {
            statusLabel.setText(status);
            statusLabel.setBackground(Color.GRAY);
            statusLabel.setForeground(Color.RED);
//            statusLabel.setFont(Font.BOLD);
            doLayout();
        }
        void showFailure(String demo, String status) {
            showFailure(demo+": "+status);
        }

        
        public void actionPerformed(ActionEvent e) {
            // find button
            for(int i=0;i<buttonList.length;i++) {
                if(e.getSource() == buttonList[i]) {
                    String demoShort = demoList[i];
                    String demo = demoBase+'.'+demoShort;
                    showStatus(demoShort, "launching");
                    try {
                        Class c = Class.forName(demo);
                        String args[] = new String[0];
                        Class params[] = new Class[1];
                        params[0] = args.getClass();
                        Method m = c.getMethod("main", params );
                        Object[] argList = { args };
                        m.invoke(null, argList);
                        showStatus(demoShort, "launched.");
                    } catch (ClassNotFoundException e1) {
                        showFailure(demoShort,e1.toString());
                        e1.printStackTrace();
                    } catch (SecurityException se) {
                        showFailure(demoShort,se.toString());
                        se.printStackTrace();
                    } catch (NoSuchMethodException nsme) {
                        showFailure(demoShort,nsme.toString());
                        nsme.printStackTrace();
                    } catch (IllegalArgumentException iae) {
                        showFailure(demoShort,iae.toString());
                        iae.printStackTrace();
                    } catch (IllegalAccessException iae) {
                        showFailure(demoShort,iae.toString());
                        iae.printStackTrace();
                    } catch (InvocationTargetException ite) {
                        showFailure(demoShort,ite.toString());
                        ite.printStackTrace();
                    }
                    repaint();
                }
            }
        }

    }
    
    /* This creates a Frame for the demo applet. */
    protected Frame createDemoFrame(DemoApplet applet) {
        return new LauncherFrame(applet);
    }

    /**
     * The main function which defines the behavior of the Demo
     * applet when an applet is started.
     */
    public static void main(String[] args) {
        new Launcher().showDemo();
    }
}
