import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.HashMap;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import ag.ion.bion.officelayer.NativeView;
import ag.ion.bion.officelayer.application.IOfficeApplication;
import ag.ion.bion.officelayer.application.OfficeApplicationRuntime;
import ag.ion.bion.officelayer.desktop.IFrame;
import ag.ion.bion.officelayer.document.DocumentDescriptor;
import ag.ion.bion.officelayer.document.IDocument;
import ag.ion.bion.officelayer.filter.RTFFilter;
import ag.ion.bion.officelayer.text.ITextDocument;
import ag.ion.bion.officelayer.text.ITextRange;
import ag.ion.bion.officelayer.text.IViewCursor;
import ag.ion.noa.frame.ILayoutManager;

import com.sun.star.beans.XPropertySet;
import com.sun.star.frame.XLayoutManager;
import com.sun.star.ui.XUIElement;
import com.sun.star.uno.UnoRuntime;

public class TestApp extends JFrame {

  private IOfficeApplication officeApplication = null;
  private JPanel             panel             = null;
  private IFrame             officeFrame       = null;
  private ITextDocument      document          = null;
  private JPanel             noaPanel          = null;

  public TestApp() {
    super(TestApp.class.getName());
    getContentPane().setLayout(new GridLayout(2, 1));

    JButton buttonPut = new JButton("Put Text at cursor position");
    getContentPane().add(buttonPut);

    buttonPut.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        try {
          insertTextAtCurrentPosition("Hello World.");
        }
        catch (Exception exception) {
          exception.printStackTrace();
        }
      }
    });

    JButton buttonSave = new JButton("Save to p:/test.odt, p:/test1.odt, p:/test2.odt, p:/test2.pdf");
    getContentPane().add(buttonSave);

    buttonSave.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        try {
          ByteArrayOutputStream tempOut = new ByteArrayOutputStream();
          document.getPersistenceService().store(tempOut);
          ByteArrayInputStream tempIn = new ByteArrayInputStream(tempOut.toByteArray());
          tempOut.close();
          IDocument tmpDoc = officeApplication.getDocumentService().loadDocument(tempIn,
              DocumentDescriptor.DEFAULT_HIDDEN);
          tempIn.close();
          OutputStream finalOut = new ByteArrayOutputStream();
          tmpDoc.getPersistenceService().export(finalOut, new RTFFilter());
          finalOut.close();
          tmpDoc.close();
        }
        catch (Exception exception) {
          exception.printStackTrace();
        }
      }
    });

    panel = new JPanel();
    panel.setLayout(new GridLayout());
    getContentPane().add(panel);

    noaPanel = new JPanel();
    panel.add(noaPanel);
    setSize(1024, 800);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);
    fillNOAPanel();
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent windowEvent) {
        try {
          if (document != null)
            document.close();
          document = null;
          if (officeApplication != null) {
            officeApplication.dispose();
            officeApplication = null;
          }
        }
        catch (Exception exception) {
          //do not consume
        }
      }
    });
  }

  private void insertTextAtCurrentPosition(String text) {
    IViewCursor viewCursor = document.getViewCursorService().getViewCursor();
    ITextRange textRange = viewCursor.getStartTextRange();
    textRange.setText(text);
  }

  private void fillNOAPanel() {
    if (noaPanel != null) {
      try {
        if (officeApplication == null)
          officeApplication = startOOO();
        officeFrame = constructOOOFrame(officeApplication, noaPanel);
        document = (ITextDocument) officeApplication.getDocumentService().constructNewDocument(officeFrame,
            IDocument.WRITER,
            DocumentDescriptor.DEFAULT);
        //hide all none persistant start
        ILayoutManager layoutManager = officeFrame.getLayoutManager();
        XLayoutManager xLayoutManager = layoutManager.getXLayoutManager();
        for (int i = 0; i < ILayoutManager.ALL_BARS_URLS.length; i++) {
          String url = ILayoutManager.ALL_BARS_URLS[i];
          XUIElement element = xLayoutManager.getElement(url);
          if (element != null) {
            XPropertySet xps = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, element);
            xps.setPropertyValue("Persistent", new Boolean(false));
            xLayoutManager.hideElement(url);
          }
        }
        //hide all none persistant end
        noaPanel.setVisible(true);
      }
      catch (Throwable throwable) {
        noaPanel.add(new JLabel("An error occured while creating the NOA panel: " + throwable.getMessage()));
      }
    }
  }

  private IOfficeApplication startOOO() throws Throwable {
    HashMap configuration = new HashMap();
    configuration.put(IOfficeApplication.APPLICATION_HOME_KEY, "c:/Programme/OpenOffice.org 3");
    configuration.put(IOfficeApplication.APPLICATION_TYPE_KEY, IOfficeApplication.LOCAL_APPLICATION);
    IOfficeApplication officeAplication = OfficeApplicationRuntime.getApplication(configuration);

    officeAplication.setConfiguration(configuration);
    officeAplication.activate();
    officeAplication.getDesktopService().activateTerminationPrevention();
    return officeAplication;
  }

  private IFrame constructOOOFrame(IOfficeApplication officeApplication, final Container parent)
      throws Throwable {
    final NativeView nativeView = new NativeView(System.getProperty("user.dir") + "/lib");
    parent.add(nativeView);
    parent.addComponentListener(new ComponentAdapter() {
      public void componentResized(ComponentEvent e) {
        nativeView.setPreferredSize(new Dimension(parent.getWidth() - 5, parent.getHeight() - 5));
        parent.getLayout().layoutContainer(parent);
      }
    });
    nativeView.setPreferredSize(new Dimension(parent.getWidth() - 5, parent.getHeight() - 5));
    parent.getLayout().layoutContainer(parent);
    IFrame officeFrame = officeApplication.getDesktopService().constructNewOfficeFrame(nativeView);
    parent.validate();
    return officeFrame;
  }

  public static void main(String[] argv) {
    new TestApp();
  }
}

