/*******************************************************************************
 * Copyright (c) 2015 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.display.builder.runtime.script;

import java.util.List;

import org.csstudio.display.builder.model.DisplayModel;
import org.csstudio.display.builder.model.Widget;
import org.csstudio.display.builder.model.properties.ScriptInfo;
import org.csstudio.display.builder.model.properties.ScriptPV;
import org.csstudio.display.builder.runtime.ResourceUtil;
import org.csstudio.display.builder.runtime.RuntimeUtil;
import org.csstudio.vtype.pv.PV;
import org.csstudio.vtype.pv.PVListener;
import org.csstudio.vtype.pv.PVPool;
import org.epics.vtype.VType;

/** Handler for one script of a widget.
 *
 *  <p>Compiles script, connects to PVs,
 *  invokes script on trigger PV changes.
 *
 *  @author Kay Kasemir
 */
public class RuntimeScriptHandler implements PVListener
{
    private final Widget widget;
    private final List<ScriptPV> infos;
    private final Script script;
    private final PV[] pvs;

    /** @param widget Widget on which the script is invoked
     *  @param script_info Script to handle
     *  @throws Exception on error
     */
    public RuntimeScriptHandler(final Widget widget, final ScriptInfo script_info) throws Exception
    {
        this.widget = widget;
        this.infos = script_info.getPVs();

        // Compile script
        final String script_name = script_info.getFile();
        final ScriptSupport scripting = RuntimeUtil.getScriptSupport(widget);

        final DisplayModel model = RuntimeUtil.getDisplayModel(widget);
        final String parent_display = model.getUserData(DisplayModel.USER_DATA_INPUT_FILE);
        final String resolved = ResourceUtil.resolveDisplay(parent_display, script_name);
        script = scripting.compile(script_name, ResourceUtil.openInputStream(resolved));

        // Create PVs
        pvs = new PV[infos.size()];
        for (int i=0; i<pvs.length; ++i)
            pvs[i] = PVPool.getPV(infos.get(i).getName());

        // Subscribe to trigger PVs
        for (int i=0; i<pvs.length; ++i)
            if (infos.get(i).isTrigger())
                pvs[i].addListener(this);
    }

    private void invoke_script()
    {
        script.submit(widget, pvs);
    }

    /** Must be invoked to dispose PVs */
    public void shutdown()
    {
        for (int i=0; i<pvs.length; ++i)
        {
            if (infos.get(i).isTrigger())
                pvs[i].removeListener(this);
            PVPool.releasePV(pvs[i]);
        }
    }

    @Override
    public void valueChanged(final PV pv, final VType value)
    {
        RuntimeUtil.getExecutor().execute(this::invoke_script);
    }

    @Override
    public void disconnected(final PV pv)
    {
        // NOP
    }

    @Override
    public void permissionsChanged(final PV pv, final boolean readonly)
    {
        // NOP
    }
}
@@ -652,16 +652,138 @@
 idget;%0D%0A
+import org.csstudio.display.builder.model.macros.MacroHandler;%0D%0Aimport org.csstudio.display.builder.model.macros.Macros;%0D%0A
 import o
@@ -1864,24 +1864,86 @@
 etPVs();%0D%0A%0D%0A
+        final Macros macros = widget.getEffectiveMacros();%0D%0A%0D%0A
         // C
@@ -1991,16 +1991,45 @@
 t_name =
+ MacroHandler.replace(macros,
  script_
@@ -2042,16 +2042,17 @@
 etFile()
+)
 ;%0D%0A     
@@ -2590,60 +2590,155 @@
     
+%7B%0D%0A
     
-pvs%5Bi%5D = PVPool.getPV(infos.get(i).getName());%0D%0A
+        final String pv_name = MacroHandler.replace(macros, infos.get(i).getName());%0D%0A            pvs%5Bi%5D = PVPool.getPV(pv_name);%0D%0A        %7D
 %0D%0A  

Support macros in script name & input PV names