/**************************************************************
 *
 * 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 com.sun.star.uno.XComponentContext;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JTabbedPane;
import javax.swing.KeyStroke;



public class SwingDialogProvider implements XDialogProvider{

    private JPopupMenu m_jPopupMenu = new JPopupMenu();
    private XComponentContext m_xComponentContext;
    private Inspector._Inspector m_oInspector;
    private JDialog m_jInspectorDialog = new JDialog();
    private JTabbedPane m_jTabbedPane1 = new JTabbedPane();
    private Container cp;

    private JMenu jMnuOptions = new JMenu("Options");
    private JRadioButtonMenuItem jJavaMenuItem = null;
    private JRadioButtonMenuItem jCPlusPlusMenuItem = null;
    private JRadioButtonMenuItem jBasicMenuItem = null;

    /** Creates a new instance of SwingPopupMentuProvider */
    public SwingDialogProvider(Inspector._Inspector _oInspector, String _sTitle) {
        m_oInspector = _oInspector;
        m_xComponentContext = _oInspector.getXComponentContext();
        insertMenus();
        initializePopupMenu();
        cp = m_jInspectorDialog.getContentPane();
        cp.setLayout(new java.awt.BorderLayout(0, 10));
        m_jTabbedPane1.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
        m_jInspectorDialog.addWindowListener(new InspectorWindowAdapter());
        m_jInspectorDialog.addComponentListener(new InspectorComponentAdapter());
        m_jInspectorDialog.setTitle(_sTitle);
        m_jInspectorDialog.setLocation(100, 50);
        m_jInspectorDialog.getContentPane().add(m_jTabbedPane1);
    }



        public JDialog getDialog(){
            return m_jInspectorDialog;
        }


        public void addMenuBar(JMenuBar _jMenuBar){
            getDialog().setJMenuBar(_jMenuBar);
        }


        public void  removeTabPaneByIndex(int _nIndex){
            if (_nIndex > -1){
                String sSelInspectorPanelTitle = m_jTabbedPane1.getTitleAt(_nIndex);
                m_jTabbedPane1.remove(_nIndex);
                m_oInspector.getInspectorPages().remove(sSelInspectorPanelTitle);
            }
        }


        public void selectInspectorPageByIndex(int nTabIndex){
            m_jTabbedPane1.setSelectedIndex(nTabIndex);
        }


        public int getInspectorPageCount(){
            return  m_jTabbedPane1.getTabCount();
        }


        public JTabbedPane getTabbedPane(){
            return m_jTabbedPane1;
        }


        public InspectorPane getSelectedInspectorPage(){
            int nIndex = m_jTabbedPane1.getSelectedIndex();
            return getInspectorPage(nIndex);
        }


        public InspectorPane getInspectorPage(int _nIndex){
            InspectorPane oInspectorPane = null;
            if (_nIndex > -1){
                JPanel jPnlContainerInspectorPanel = (JPanel) m_jTabbedPane1.getComponentAt(_nIndex);
                String sInspectorPanelTitle = m_jTabbedPane1.getTitleAt(_nIndex);
                oInspectorPane = (InspectorPane) m_oInspector.getInspectorPages().get(sInspectorPanelTitle);
            }
            return oInspectorPane;
        }


        public void removeTabPanes(){
            int nCount = m_jTabbedPane1.getTabCount();
            if (nCount > 0){
                for (int i = nCount-1; i >= 0; i--){
                    removeTabPaneByIndex(i);
                }
            }
        }

        public void removeSelectedTabPane(){
            int nIndex = getTabbedPane().getSelectedIndex();
            removeTabPaneByIndex(nIndex);
        }


        private class InspectorComponentAdapter extends ComponentAdapter{
            public void componentHidden(ComponentEvent e){
                m_jInspectorDialog.pack();
                m_jInspectorDialog.invalidate();

            }

            public void componentShown(ComponentEvent e){
                m_jInspectorDialog.pack();
                m_jInspectorDialog.invalidate();
            }
        }

        private class InspectorWindowAdapter extends WindowAdapter{
            public void windowClosed(WindowEvent e){
                removeTabPanes();
                m_oInspector.disposeHiddenDocuments();
            }

            public void windowClosing(WindowEvent e){
                removeTabPanes();
                m_oInspector.disposeHiddenDocuments();
            }
        }



        private void initializePopupMenu(){
            m_jPopupMenu.add(getInspectMenuItem("Inspect"));
            m_jPopupMenu.add(getSourceCodeMenuItem(SADDTOSOURCECODE));
            m_jPopupMenu.add(getInvokeMenuItem(SINVOKE));
            m_jPopupMenu.addSeparator();
            m_jPopupMenu.add(getHelpMenuItem("Help"));
        }


        private void addOpenDocumentMenu(JMenu _jMnuRoot){
            ActionListener oActionListener = new ActionListener(){
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    String sTDocUrl = evt.getActionCommand();
                    m_oInspector.inspectOpenDocument(sTDocUrl);
                }
            };
            String[] sTDocUrls = m_oInspector.getTDocUrls();
            String[] sTDocTitles = m_oInspector.getTDocTitles(sTDocUrls);
            for (int i = 0; i < sTDocUrls.length; i++){
                addSingleMenuItem(_jMnuRoot, sTDocTitles[i], sTDocUrls[i], oActionListener);
            }
        }


        private void addApplicationDocumentMenu(JMenu _jMnuRoot){
            ActionListener oActionListener = new ActionListener(){
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    String sApplicationDocUrl = evt.getActionCommand();
                    m_oInspector.inspectOpenEmptyDocument(sApplicationDocUrl);
                }
            };
            String[][] sApplUrls = m_oInspector.getApplicationUrls();
            for (int i = 0; i < sApplUrls.length; i++){
                addSingleMenuItem(_jMnuRoot, sApplUrls[i][1], sApplUrls[i][0], oActionListener);
            }
        }


        private void addSingleMenuItem(JMenu _jMnuOpenDocs, String _sTitle, String _sActionCommand, ActionListener _oActionListener){
            javax.swing.JMenuItem jMnuItemOpenDoc = new javax.swing.JMenuItem(_sTitle);
            jMnuItemOpenDoc.setActionCommand(_sActionCommand);
            jMnuItemOpenDoc.addActionListener(_oActionListener);
            _jMnuOpenDocs.add(jMnuItemOpenDoc);
        }


        private void addHelpMenu(JMenuBar _jInspectMenuBar){
            JMenu jMnuHelp = new JMenu("Help");
            jMnuHelp.add(getHelpMenuItem("Idl-Help"));
            _jInspectMenuBar.add(jMnuHelp);
        }


        private JMenuItem getHelpMenuItem(String _sMenuTitle){
            JMenuItem jMnuHelpItem = new JMenuItem(_sMenuTitle);
            jMnuHelpItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0));
            jMnuHelpItem.setMnemonic('H');
            jMnuHelpItem.addActionListener(new ActionListener(){
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    m_oInspector.openIdlFileforSelectedNode();
                }
            });
            return jMnuHelpItem;
        }

        private void addFileMenu(JMenuBar _jInspectMenuBar){
            JMenu jMnuFile = new JMenu("File");
            JMenuItem jMnuItemRemoveInspector = new JMenuItem("Remove");
            jMnuItemRemoveInspector.addActionListener(new ActionListener(){
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    removeSelectedTabPane();
                }
            });
            jMnuFile.add(jMnuItemRemoveInspector);
            JMenuItem jMnuItemExit = new JMenuItem("Exit");
            jMnuItemExit.addActionListener(new ActionListener(){
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    getDialog().dispose();
                }
            });
            jMnuFile.add(jMnuItemExit);
            _jInspectMenuBar.add(jMnuFile);
        }

        private JMenuItem getInspectMenuItem(String _sLabel){
            JMenuItem jMnuSelectedObject = new JMenuItem(_sLabel);
            jMnuSelectedObject.addActionListener(new ActionListener(){
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    m_oInspector.inspectSelectedNode();
                }
            });
            return jMnuSelectedObject;
        }


        private JMenuItem getSourceCodeMenuItem(String _sLabel){
            JMenuItem jMnuSelectedObject = new JMenuItem(_sLabel);
            jMnuSelectedObject.addActionListener(new ActionListener(){
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    m_oInspector.addSourceCodeOfSelectedNode();
                }
            });
            return jMnuSelectedObject;
        }

        private JMenuItem getInvokeMenuItem(String _sLabel){
            JMenuItem jMnuSelectedObject = new JMenuItem(_sLabel);
            jMnuSelectedObject.addActionListener(new ActionListener(){
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    m_oInspector.invokeSelectedMethod();
                }
            });
            return jMnuSelectedObject;
        }


        private void addInspectMenu(JMenuBar _jInspectMenuBar){
            JMenu jMnuInspect = new JMenu("Inspect");
            addApplicationDocumentMenu(jMnuInspect);
            jMnuInspect.addSeparator();
            addGlobalServiceManagerMenu(jMnuInspect);
            jMnuInspect.addSeparator();
            jMnuInspect.add(getInspectMenuItem("Selected Object"));
            jMnuInspect.addSeparator();
            addOpenDocumentMenu(jMnuInspect);
            _jInspectMenuBar.add(jMnuInspect);
        }

        public int getLanguage(){
            return XLanguageSourceCodeGenerator.nJAVA;
        }


        public void selectSourceCodeLanguage(int _nLanguage){
            switch (_nLanguage){
                case XLanguageSourceCodeGenerator.nJAVA:
                    jJavaMenuItem.setSelected(true);
                    break;
                case XLanguageSourceCodeGenerator.nCPLUSPLUS:
                    jCPlusPlusMenuItem.setSelected(true);
                    break;
                case XLanguageSourceCodeGenerator.nBASIC:
                    jBasicMenuItem.setSelected(true);
                    break;
                default:
                    System.out.println("Warning: Sourcecode language is not defined!");
            }
        }

        private JRadioButtonMenuItem addLanguageMenuItem(ButtonGroup _group, String _sLanguageTitle, boolean _bSelect, char _sMnemonic, final int _nLanguage){
            JRadioButtonMenuItem jMenuItem = new JRadioButtonMenuItem(_sLanguageTitle, _bSelect);
            jMenuItem.setMnemonic(_sMnemonic);
            _group.add(jMenuItem);
            jMenuItem.addActionListener(new ActionListener(){
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    m_oInspector.setSourceCodeLanguage(_nLanguage);
                }
            });
            return jMenuItem;
        }


        public String getIDLPath(){
            return this.m_oInspector.getIDLPath();
        }

        private void addOptionsMenu(JMenuBar _jInspectMenuBar){
            ButtonGroup oButtonGroup = new ButtonGroup();
            jJavaMenuItem = addLanguageMenuItem(oButtonGroup, "Generate Java Sourcecode", true, 'J', XLanguageSourceCodeGenerator.nJAVA);
            jMnuOptions.add(jJavaMenuItem);
            jCPlusPlusMenuItem = addLanguageMenuItem(oButtonGroup, "Generate C++ Sourcecode", false, 'C', XLanguageSourceCodeGenerator.nCPLUSPLUS);
            jMnuOptions.add(jCPlusPlusMenuItem);
            jBasicMenuItem = addLanguageMenuItem(oButtonGroup, "Generate OpenOffice.org Basic Sourcecode", false, 'B', XLanguageSourceCodeGenerator.nBASIC);
            jMnuOptions.add(jBasicMenuItem);
            jMnuOptions.addSeparator();
            JMenuItem jMenuItem = new JMenuItem("Path to SDK-Installation");
            jMenuItem.setMnemonic('I');
            jMenuItem.addActionListener(new ActionListener(){
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    m_oInspector.assignSDKPath();
                }
            });

            jMnuOptions.add(jMenuItem);
            _jInspectMenuBar.add(jMnuOptions);
        }


        private void insertMenus(){
            JMenuBar jMenuBar1 = new javax.swing.JMenuBar();
            addFileMenu(jMenuBar1);
            addInspectMenu(jMenuBar1);
            JMenu jMnuEdit = new JMenu("Edit");
            JMenu jMnuView = new JMenu("View");
            addOptionsMenu(jMenuBar1);
            jMenuBar1.setFont(new java.awt.Font("Dialog", 0, 12));
            jMenuBar1.add(jMnuEdit);
            jMenuBar1.add(jMnuView);
            addHelpMenu(jMenuBar1);
            addMenuBar(jMenuBar1);
        }

        private void addGlobalServiceManagerMenu(JMenu _jMnuRoot){
            JMenuItem jMnuGlobalServiceManager = new JMenuItem("Global Service Manager");
            jMnuGlobalServiceManager.addActionListener(new ActionListener(){
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    m_oInspector.inspect(m_xComponentContext.getServiceManager(), "Global ServiceManager");
                }
            });
            _jMnuRoot.add(jMnuGlobalServiceManager);
        }



        public void enablePopupMenuItem(String _sMenuTitle, boolean _bdoEnable){
            Component[] oComponents = m_jPopupMenu.getComponents();
            for (int i = 0; i < oComponents.length; i++){
                if (oComponents[i] instanceof JMenuItem){
                    JMenuItem jMenuItem = (JMenuItem) oComponents[i];
                    if (jMenuItem.getText().equals(_sMenuTitle)){
                        jMenuItem.setEnabled(_bdoEnable);
                    }
                }
            }
        }


        public void showPopUpMenu(Object _invoker, int x, int y) throws ClassCastException{
            if (_invoker instanceof Component){
                m_jPopupMenu.show((Component) _invoker, x, y);
            }
        }


    public void show(int _nPageIndex){
        Dimension aDimension = m_jInspectorDialog.getSize();
        selectInspectorPageByIndex(_nPageIndex);
        if (_nPageIndex > 0){
            m_jInspectorDialog.setSize(aDimension);
        }
        else{
            m_jInspectorDialog.pack();
        }
//            m_jInspectorDialog.paint(m_jInspectorDialog.getGraphics());
        m_jInspectorDialog.setVisible(true);
    }

        public void paint(){
            m_jTabbedPane1.paintImmediately(m_jTabbedPane1.getBounds());
        }


        public void addInspectorPage(String _sTitle, Object _oContainer) throws ClassCastException{
            if (_oContainer instanceof Component){
                m_jTabbedPane1.addTab(_sTitle, (Component) _oContainer);
            }
        }
}
