import com.jniwrapper.win32.automation.types.BStr;
import com.jniwrapper.win32.automation.types.Variant;
import com.jniwrapper.win32.automation.types.VariantBool;
import com.jniwrapper.win32.com.types.ClsCtx;
import com.jniwrapper.win32.ole.OleFunctions;
import word.word.*;

import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.io.File;

/**
 * This sample shows how to edit the bookmark's text in the Word document.
 */
public class WordBookmarksSample
{
    private final _Document document;
    private final _Application application;
    private final File documentFile;

    /**
     * Creates and initializes the instance of the class with a document already opened in it.
     *
     * @throws RuntimeException if Word was unable to open the specified document.
     */
    public WordBookmarksSample()
    {
        OleFunctions.oleInitialize();
        application = Application.create(ClsCtx.LOCAL_SERVER);
        application.setVisible(new VariantBool(false));
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileFilter(new WordFileFilter());

        int result = fileChooser.showOpenDialog(null);

        if (result == JFileChooser.APPROVE_OPTION)
        {
            documentFile = fileChooser.getSelectedFile().getAbsoluteFile();

            try
            {
                System.out.println("Opening document: " + documentFile.getAbsolutePath());
                Variant unspecifiedParameter = Variant.createUnspecifiedParameter();
                Documents documents = application.getDocuments();
                document = documents.add(new Variant(documentFile.getAbsolutePath()),
                        unspecifiedParameter,
                        unspecifiedParameter,
                        unspecifiedParameter);
                documents.setAutoDelete(false);
                documents.release();

            }
            catch (Exception e)
            {
                destroy();
                throw new RuntimeException("Unable to open document " + documentFile.getName(), e);
            }
        }
        else
        {
            destroy();
            throw new RuntimeException("The document wasn't selected");
        }
    }

    /**
     * Closes document, application and releases all resources. Must be called when the instance
     * is not necessary anymore.
     */
    public void destroy()
    {
        if (application != null && !application.isNull())
        {
            Variant unspecifiedParameter = Variant.createUnspecifiedParameter();
            if (document != null && !document.isNull())
            {
                document.close(new Variant(false),
                        unspecifiedParameter,
                        unspecifiedParameter);
                document.setAutoDelete(false);
                document.release();
            }
            application.quit(new Variant(false),
                    unspecifiedParameter,
                    unspecifiedParameter);
            application.setAutoDelete(false);
            application.release();
        }
    }

    /**
     * Changes the bookmark text is bookmark exists and its text is not empty.
     *
     * @param bookmarkName the name of the bookmark to change
     * @param bookmarkText the new text for the bookmark
     */
    public void changeBookmarkText(String bookmarkName, String bookmarkText)
    {
        Bookmarks bookmarks = document.getBookmarks();
        if (bookmarks.exists(new BStr(bookmarkName)).getBooleanValue() && bookmarkText.length() > 0)
        {
            System.out.println("Changing bookmark text: " + bookmarkName);
            Bookmark bookmark = bookmarks.item(new Variant(bookmarkName));
            Range bookmarkRange = bookmark.getRange();
            System.out.println("Previous text: " + bookmarkRange.getText().getValue());
            System.out.println("New text: " + bookmarkText);
            bookmarkRange.setText(new BStr(bookmarkText));

            bookmark.setAutoDelete(false);
            bookmark.release();
            bookmarkRange.setAutoDelete(false);
            bookmarkRange.release();
        }
        bookmarks.setAutoDelete(false);
        bookmarks.release();
    }

    /**
     * Saves the result of work to file
     */
    public void saveDocument()
    {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileFilter(new WordFileFilter());
        int result = fileChooser.showSaveDialog(null);
        if (result == JFileChooser.APPROVE_OPTION)
        {
            String editedFilePath = fileChooser.getSelectedFile().getAbsolutePath();
            System.out.println("Saving result to " + editedFilePath);
            Variant unspecifiedParameter = Variant.createUnspecifiedParameter();
            document.saveAs(new Variant(editedFilePath),
                    new Variant(WdSaveFormat.wdFormatDocument97),
                    new Variant(false),
                    unspecifiedParameter,
                    new Variant(false),
                    unspecifiedParameter,
                    unspecifiedParameter,
                    unspecifiedParameter,
                    unspecifiedParameter,
                    unspecifiedParameter,
                    unspecifiedParameter,
                    unspecifiedParameter,
                    unspecifiedParameter,
                    unspecifiedParameter,
                    new Variant(WdLineEndingType.wdCRLF),
                    unspecifiedParameter);
        }
    }

    public static void main(String[] args) throws Exception
    {
        WordBookmarksSample bookmarksSample = new WordBookmarksSample();

        String bookmarkName = JOptionPane.showInputDialog("Please enter bookmark name:");
        String bookmarkText = JOptionPane.showInputDialog("Please enter bookmark new text:");

        bookmarksSample.changeBookmarkText(bookmarkName, bookmarkText);
        bookmarksSample.saveDocument();
        bookmarksSample.destroy();
    }

    private class WordFileFilter extends FileFilter
    {
        public boolean accept(File file)
        {
            return file.getName().toLowerCase().endsWith(".doc")
                    || file.isDirectory();
        }

        public String getDescription()
        {
            return "Word document (*.doc)";
        }
    }
}

