001package jmri.jmrit.logixng.actions;
002
003import java.beans.PropertyChangeEvent;
004import java.beans.PropertyChangeListener;
005import java.util.*;
006
007import jmri.*;
008import jmri.jmrit.logixng.*;
009import jmri.jmrit.logixng.util.LogixNG_SelectNamedBean;
010
011/**
012 * Runs an engine.
013 * This action reads an analog expression with the loco address and sets its
014 * speed according to an alaog expression and the direction according to a
015 * digital expression.
016 *
017 * @author Daniel Bergqvist Copyright 2019
018 */
019public class ActionLightIntensity extends AbstractDigitalAction
020        implements FemaleSocketListener, PropertyChangeListener {
021
022    public static final int INTENSITY_SOCKET = 0;
023
024    private final LogixNG_SelectNamedBean<VariableLight> _selectNamedBean =
025            new LogixNG_SelectNamedBean<>(
026                    this, VariableLight.class, InstanceManager.getDefault(VariableLightManager.class), this);
027
028    private String _intensitySocketSystemName;
029    private final FemaleAnalogExpressionSocket _intensitySocket;
030
031
032    public ActionLightIntensity(String sys, String user) {
033        super(sys, user);
034        _intensitySocket = InstanceManager.getDefault(AnalogExpressionManager.class)
035                .createFemaleSocket(this, this, Bundle.getMessage("ActionLightIntensity_SocketName"));
036    }
037
038    @Override
039    public Base getDeepCopy(Map<String, String> systemNames, Map<String, String> userNames) throws JmriException {
040        DigitalActionManager manager = InstanceManager.getDefault(DigitalActionManager.class);
041        String sysName = systemNames.get(getSystemName());
042        String userName = userNames.get(getSystemName());
043        if (sysName == null) sysName = manager.getAutoSystemName();
044        ActionLightIntensity copy = new ActionLightIntensity(sysName, userName);
045        copy.setComment(getComment());
046        _selectNamedBean.copy(copy._selectNamedBean);
047        return manager.registerAction(copy).deepCopyChildren(this, systemNames, userNames);
048    }
049
050    public LogixNG_SelectNamedBean<VariableLight> getSelectNamedBean() {
051        return _selectNamedBean;
052    }
053
054    /** {@inheritDoc} */
055    @Override
056    public Category getCategory() {
057        return Category.ITEM;
058    }
059
060    /** {@inheritDoc} */
061    @Override
062    public void execute() throws JmriException {
063        VariableLight light = _selectNamedBean.evaluateNamedBean(getConditionalNG());
064
065        if (light == null) {
066//            log.warn("light is null");
067            return;
068        }
069
070        double intensity = 0.0;
071
072        if (_intensitySocket.isConnected()) {
073            intensity =
074                    ((MaleAnalogExpressionSocket)_intensitySocket.getConnectedSocket())
075                            .evaluate();
076        }
077
078        if (intensity < 0.0) intensity = 0.0;
079        if (intensity > 100.0) intensity = 100.0;
080
081        light.setTargetIntensity(intensity/100.0);
082    }
083
084    @Override
085    public FemaleSocket getChild(int index) throws IllegalArgumentException, UnsupportedOperationException {
086        switch (index) {
087            case INTENSITY_SOCKET:
088                return _intensitySocket;
089
090            default:
091                throw new IllegalArgumentException(
092                        String.format("index has invalid value: %d", index));
093        }
094    }
095
096    @Override
097    public int getChildCount() {
098        return 1;
099    }
100
101    @Override
102    public void connected(FemaleSocket socket) {
103        if (socket == _intensitySocket) {
104            _intensitySocketSystemName = socket.getConnectedSocket().getSystemName();
105        } else {
106            throw new IllegalArgumentException("unkown socket");
107        }
108    }
109
110    @Override
111    public void disconnected(FemaleSocket socket) {
112        if (socket == _intensitySocket) {
113            _intensitySocketSystemName = null;
114        } else {
115            throw new IllegalArgumentException("unkown socket");
116        }
117    }
118
119    @Override
120    public String getShortDescription(Locale locale) {
121        return Bundle.getMessage(locale, "ActionLightIntensity_Short");
122    }
123
124    @Override
125    public String getLongDescription(Locale locale) {
126        String namedBean = _selectNamedBean.getDescription(locale);
127
128        return Bundle.getMessage(locale, "ActionLightIntensity_Long", namedBean);
129    }
130
131    public FemaleAnalogExpressionSocket getIntensitySocket() {
132        return _intensitySocket;
133    }
134
135    public String getIntensitySocketSystemName() {
136        return _intensitySocketSystemName;
137    }
138
139    public void setIntensitySystemName(String systemName) {
140        _intensitySocketSystemName = systemName;
141    }
142
143    /** {@inheritDoc} */
144    @Override
145    public void setup() {
146        try {
147            if ( !_intensitySocket.isConnected()
148                    || !_intensitySocket.getConnectedSocket().getSystemName()
149                            .equals(_intensitySocketSystemName)) {
150
151                String socketSystemName = _intensitySocketSystemName;
152                _intensitySocket.disconnect();
153                if (socketSystemName != null) {
154                    MaleSocket maleSocket =
155                            InstanceManager.getDefault(AnalogExpressionManager.class)
156                                    .getBySystemName(socketSystemName);
157                    _intensitySocket.disconnect();
158                    if (maleSocket != null) {
159                        _intensitySocket.connect(maleSocket);
160                        maleSocket.setup();
161                    } else {
162                        log.error("cannot load analog expression {}", socketSystemName);
163                    }
164                }
165            } else {
166                _intensitySocket.getConnectedSocket().setup();
167            }
168        } catch (SocketAlreadyConnectedException ex) {
169            // This shouldn't happen and is a runtime error if it does.
170            throw new RuntimeException("socket is already connected");
171        }
172    }
173
174    /** {@inheritDoc} */
175    @Override
176    public void registerListenersForThisClass() {
177        _selectNamedBean.registerListeners();
178        _listenersAreRegistered = true;
179    }
180
181    /** {@inheritDoc} */
182    @Override
183    public void unregisterListenersForThisClass() {
184        _selectNamedBean.unregisterListeners();
185        _listenersAreRegistered = false;
186    }
187
188    /** {@inheritDoc} */
189    @Override
190    public void disposeMe() {
191    }
192
193    /** {@inheritDoc} */
194    @Override
195    public void propertyChange(PropertyChangeEvent evt) {
196        getConditionalNG().execute();
197    }
198
199    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ActionLightIntensity.class);
200
201}