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