import java.math.BigDecimal;
import java.util.HashMap;

import ag.ion.bion.officelayer.application.IOfficeApplication;
import ag.ion.bion.officelayer.application.OfficeApplicationRuntime;
import ag.ion.bion.officelayer.document.DocumentDescriptor;
import ag.ion.bion.officelayer.document.IDocument;
import ag.ion.bion.officelayer.document.IDocumentService;
import ag.ion.bion.officelayer.text.ITextCursor;
import ag.ion.bion.officelayer.text.ITextDocument;
import ag.ion.bion.officelayer.text.ITextRange;
import ag.ion.noa.search.ISearchResult;
import ag.ion.noa.search.SearchDescriptor;
import ag.ion.noa.text.TextRangeSelection;

public class OfficeHandler {

  public static void main(String[] args) {
    String oooPath = "C:/Programme/OpenOffice.org 3";
    String filePath = "p:/tests/Anrede.odt";
    String replace = "(ich bin ersetzt worden)";
    boolean hidden = true;
    boolean alwaysCloseDocs = false;
    boolean allwaysStartStop = true;
    int n = 100; //durchläuft

    try {
      OfficeHandler officeHandler = null;
      for (int i = 0; i < n; i++) {
        System.out.println("================================");
        System.out.println("============ Run " + (i + 1));
        System.out.println("================================");
        if (allwaysStartStop || i == 0) {
          officeHandler = new OfficeHandler(oooPath, filePath, replace + " "
              + (i + 1));
          officeHandler.start();
        }
        officeHandler.openEditDoc(hidden, alwaysCloseDocs);
        if (allwaysStartStop || i == n - 1) {
          officeHandler.stop();
        }
      }
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }

  private String             oooPath          = null;
  private String             filePath         = null;
  private String             replace          = null;

  private IOfficeApplication officeAplication = null;

  public OfficeHandler(String oooPath, String filePath, String replace) {
    this.oooPath = oooPath;
    this.filePath = filePath;
    this.replace = replace;
  }

  @SuppressWarnings({ "rawtypes", "unchecked" })
  public void start() throws Exception {
    printMem("before start");
    if (officeAplication == null) {
      HashMap configuration = new HashMap();
      configuration.put(IOfficeApplication.APPLICATION_HOME_KEY, oooPath);
      configuration.put(IOfficeApplication.APPLICATION_TYPE_KEY,
          IOfficeApplication.LOCAL_APPLICATION);
      officeAplication = OfficeApplicationRuntime.getApplication(configuration);
    }
    if (!officeAplication.isActive()) {
      officeAplication.activate();
    }
    printMem("after start");
  }

  public void stop() throws Exception {
    printMem("before stop");
    if (officeAplication.isActive()) {
      officeAplication.dispose();
    }
    printMem("after stop");
  }

  public void openEditDoc(boolean hidden, boolean closeWhenFinished) throws Exception {
    printMem("before openEditDoc");
    IDocumentService documentService = officeAplication.getDocumentService();

    //Hidden loading
    DocumentDescriptor documentDescriptor = DocumentDescriptor.DEFAULT;
    documentDescriptor.setHidden(hidden);
    IDocument document = documentService.loadDocument(filePath, documentDescriptor);
    ITextDocument textDocument = (ITextDocument) document;

    ITextCursor textCursor = textDocument.getTextService().getText().getTextCursorService().getTextCursor();
    textCursor.gotoStart(false);

    searchAndReplace(textCursor, replace, textDocument);

    textDocument.getTextFieldService().refresh();

    //Abschliessendes Speichern und Schliessen vom doc
    if (closeWhenFinished) {
      document.getPersistenceService().store();
      printMem("before doc.close");
      textDocument.close();
      printMem("after doc.close");
    }
    printMem("after openEditDoc");
  }

  public void searchAndReplace(ITextCursor cursor, String r, ITextDocument textDocument)
      throws Exception {
    printMem("before replace");
    cursor.gotoStart(false);
    cursor.gotoNextParagraph(true);
    String search = cursor.getString();
    search = search.trim();
    SearchDescriptor searchDescriptor = new SearchDescriptor(search);
    searchDescriptor.setIsCaseSensitive(true);
    //Perform the search ...
    ISearchResult searchResult = textDocument.getSearchService().findFirst(searchDescriptor);
    if (!searchResult.isEmpty()) {
      //...and now select the result
      ITextRange[] textRanges = searchResult.getTextRanges();
      textDocument.setSelection(new TextRangeSelection(textRanges[0]));
      textRanges[0].setText(r);
    }
    else {
      textDocument.setSelection(new TextRangeSelection(cursor.getStart()));
      cursor.getStart().setText(r);
    }
    printMem("after replace");
  }

  public void printMem(String customMessage) {
    if (customMessage == null)
      customMessage = "";
    else {
      customMessage = customMessage + " ";
    }
    double free = getFreeMemoryMBytes();
    double total = getTotalMemorymBytes();
    System.out.println(customMessage + "Memory Total: "
        + total
        + "MB Memory Free: "
        + free
        + "MB Memory Used: "
        + round(total - free, 3)
        + "MB");
  }

  public double getFreeMemoryMBytes() {
    return round((double) Runtime.getRuntime().freeMemory() / 1024 / 1024, 3);
  }

  public double getTotalMemorymBytes() {
    return round((double) Runtime.getRuntime().totalMemory() / 1024 / 1024, 3);
  }

  public double round(double toRound, int fraction) {
    BigDecimal bd = new BigDecimal(Double.toString(toRound));
    bd = bd.setScale(fraction, BigDecimal.ROUND_HALF_UP);
    return bd.doubleValue();
  }
}

