/*******************************************************************************
 * Copyright (c) 2010 Oak Ridge National Laboratory.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 ******************************************************************************/
package org.csstudio.opibuilder.actions;

import java.io.FileNotFoundException;
import java.util.logging.Level;

import org.csstudio.openfile.IOpenDisplayAction;
import org.csstudio.opibuilder.OPIBuilderPlugin;
import org.csstudio.opibuilder.util.MacrosInput;
import org.csstudio.opibuilder.util.ResourceUtil;
import org.csstudio.ui.util.thread.UIBundlingThread;
import org.csstudio.utility.product.LinkedResourcesJob;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.osgi.util.NLS;

/** Run OPI from external program, such as alarm GUI, data browser...
 *  @author Xihui Chen
 *  @author Kay Kasemir
 */
public class ExternalOpenDisplayAction implements IOpenDisplayAction
{
    private static final String SEPARATOR = "¬";
    /** Open OPI file.
     *  @param path the path of the OPI file, it can be a workspace path, file system path, URL
     *         or a opi file in opi search path.
     *  @param data the input macros in format of {@code "macro1 = hello", "macro2 = hello2"}
     *  @throws Exception on error
     */
    public void openDisplay(final String path, final String data) throws Exception
    {
        if (path == null || path.trim().isEmpty())
        {
            OPIBuilderPlugin.getLogger().log(Level.WARNING, "ExternalOpenDisplayAction for empty display");
            return;
        }

        IPath originPath = ResourceUtil.getPathFromString(path);
        if (!originPath.isAbsolute())
        {
            originPath = ResourceUtil.getFileOnSearchPath(originPath, false);
            if (originPath == null)
                throw new FileNotFoundException(NLS.bind("File {0} doesn't exist on search path.", path));
        }
        // Parse macros
        MacrosInput macrosInput = null;
        if (data != null) {
            String[] parts = data.split(SEPARATOR);
            if (parts[0] != null && parts[0].trim().length() > 0) {
                // MacrosInput.recoverFromString(s) wants initial "true" for 'include_parent_macros'
                macrosInput = MacrosInput.recoverFromString("\"true\"," + parts[0]);
            }
            if (parts.length > 1 && parts[1] != null && parts[1].trim().length() > 0) {
                // The logic for creating links is wrapped in this job.  However,
                // we want the job to finish before continuing.
                final MacrosInput finalMacrosInput = macrosInput;
                final IPath finalOriginPath = originPath;
                final Job job = new LinkedResourcesJob(parts[1]);
                job.addJobChangeListener(new IJobChangeListener(){

                    @Override
                    public void aboutToRun(IJobChangeEvent jce) {}
                    @Override
                    public void awake(IJobChangeEvent jce) {}
                    @Override
                    public void running(IJobChangeEvent jce) {}
                    @Override
                    public void scheduled(IJobChangeEvent jce) {}
                    @Override
                    public void sleeping(IJobChangeEvent jce) {}

                    @Override
                    public void done(IJobChangeEvent jce) {
                        Runnable r = () -> { OpenTopOPIsAction.runOPI(finalMacrosInput, finalOriginPath); };
                        UIBundlingThread.getInstance().addRunnable(r);
                    }
                });
                job.schedule();
            }
        }
    }

}

@@ -1103,16 +1103,19 @@
 LS;%0A%0A/**
+%0A *
  Run OPI
@@ -1173,16 +1173,115 @@
 wser...%0A
+ * Extra data may be provided to provide macros and update shared links%0A * before opening the OPI.%0A
  *  @aut
@@ -1319,16 +1319,40 @@
 Kasemir%0A
+ *  @author Will Rogers%0A
  */%0Apubl
@@ -1467,12 +1467,23 @@
  = %22
-%C2%AC
+-share_link
 %22;%0A
+%0A
     
@@ -1683,16 +1683,33 @@
  macros 
+and shared links 
 in forma
@@ -1712,16 +1712,24 @@
 ormat of
+%0A     * 
  %7B@code 
@@ -1763,16 +1763,59 @@
  hello2%22
+ -share_link /eclipse/path=/filesystem/path
 %7D%0A     *
@@ -2569,16 +2569,148 @@
 ata 
-!
+=
 = null)
+%0A        %7B%0A            // No macros or links.%0A            OpenTopOPIsAction.runOPI(null, originPath);%0A        %7D%0A        else%0A       
  %7B%0A 
@@ -2817,32 +2817,44 @@
 ().length() %3E 0)
+%0A           
  %7B%0A             
@@ -3125,16 +3125,28 @@
 h() %3E 0)
+%0A           
  %7B%0A     
@@ -4369,32 +4369,194 @@
 ;%0A            %7D%0A
+            else%0A            %7B%0A                // We don't need to set up links.%0A                OpenTopOPIsAction.runOPI(macrosInput, originPath);%0A            %7D%0A
         %7D%0A    %7D%0A

use -share_link to denote linked resources...