001package jmri.jmrit.logixng.actions;
002
003import java.util.*;
004
005import jmri.*;
006import jmri.Block;
007import jmri.Sensor;
008import jmri.jmrit.display.layoutEditor.LayoutBlock;
009import jmri.jmrit.display.layoutEditor.LayoutBlockManager;
010import jmri.jmrit.logixng.*;
011import jmri.jmrit.logixng.util.*;
012import jmri.jmrit.logixng.util.parser.*;
013import jmri.util.ThreadingUtil;
014
015/**
016 * This action triggers a block.
017 *
018 * @author Daniel Bergqvist Copyright 2021
019 * @author Dave Sand Copyright 2021
020 */
021public class ActionBlock extends AbstractDigitalAction {
022
023    private final LogixNG_SelectNamedBean<Block> _selectNamedBean =
024            new LogixNG_SelectNamedBean<>(
025                    this, Block.class, InstanceManager.getDefault(BlockManager.class));
026
027    private final LogixNG_SelectEnum<DirectOperation> _selectEnum =
028            new LogixNG_SelectEnum<>(this, DirectOperation.values(), DirectOperation.SetOccupied);
029
030    private final LogixNG_SelectString _selectBlockValue =
031            new LogixNG_SelectString(this);
032
033
034    public ActionBlock(String sys, String user)
035            throws BadUserNameException, BadSystemNameException {
036        super(sys, user);
037    }
038
039    @Override
040    public Base getDeepCopy(Map<String, String> systemNames, Map<String, String> userNames) throws ParserException {
041        DigitalActionManager manager = InstanceManager.getDefault(DigitalActionManager.class);
042        String sysName = systemNames.get(getSystemName());
043        String userName = userNames.get(getSystemName());
044        if (sysName == null) sysName = manager.getAutoSystemName();
045        ActionBlock copy = new ActionBlock(sysName, userName);
046        copy.setComment(getComment());
047        _selectNamedBean.copy(copy._selectNamedBean);
048        _selectEnum.copy(copy._selectEnum);
049        _selectBlockValue.copy(copy._selectBlockValue);
050        return manager.registerAction(copy);
051    }
052
053    public LogixNG_SelectNamedBean<Block> getSelectNamedBean() {
054        return _selectNamedBean;
055    }
056
057    public LogixNG_SelectEnum<DirectOperation> getSelectEnum() {
058        return _selectEnum;
059    }
060
061    public LogixNG_SelectString getSelectBlockValue() {
062        return _selectBlockValue;
063    }
064
065    /** {@inheritDoc} */
066    @Override
067    public LogixNG_Category getCategory() {
068        return LogixNG_Category.ITEM;
069    }
070
071    /** {@inheritDoc} */
072    @Override
073    public void execute() throws JmriException {
074        ConditionalNG conditionalNG = getConditionalNG();
075
076        Block block = _selectNamedBean.evaluateNamedBean(conditionalNG);
077
078        if (block == null) {
079            return;
080        }
081
082        DirectOperation oper = _selectEnum.evaluateEnum(getConditionalNG());
083
084        // Variables used in lambda must be effectively final
085        DirectOperation theOper = oper;
086
087        ThreadingUtil.runOnLayoutWithJmriException(() -> {
088            Sensor sensor;
089            LayoutBlock lblk;
090
091            switch (theOper) {
092                case SetOccupied:
093                    sensor = block.getSensor();
094                    if (sensor != null) {
095                        try {
096                            sensor.setKnownState(Sensor.ACTIVE);
097                        } catch (JmriException ex) {
098                            log.debug("Exception setting sensor active");
099                        }
100                    } else {
101                        throw new JmriException(Bundle.getMessage("ActionBlock_ErrorSensor", block.getDisplayName()));
102                    }
103                    break;
104                case SetNotOccupied:
105                    sensor = block.getSensor();
106                    if (sensor != null) {
107                        try {
108                            sensor.setKnownState(Sensor.INACTIVE);
109                        } catch (JmriException ex) {
110                            log.debug("Exception setting sensor inactive");
111                        }
112                    } else {
113                        throw new JmriException(Bundle.getMessage("ActionBlock_ErrorSensor", block.getDisplayName()));
114                    }
115                    break;
116                case SetAltColorOn:
117                    lblk = InstanceManager.getDefault(LayoutBlockManager.class).getLayoutBlock(block);
118                    if (lblk != null) {
119                        lblk.setUseExtraColor(true);
120                    } else {
121                        throw new JmriException(Bundle.getMessage("ActionBlock_ErrorLayoutBlock", block.getDisplayName()));
122                    }
123                    break;
124                case SetAltColorOff:
125                    lblk = InstanceManager.getDefault(LayoutBlockManager.class).getLayoutBlock(block);
126                    if (lblk != null) {
127                        lblk.setUseExtraColor(false);
128                    } else {
129                        throw new JmriException(Bundle.getMessage("ActionBlock_ErrorLayoutBlock", block.getDisplayName()));
130                    }
131                    break;
132                case SetNullValue:
133                    block.setValue(null);
134                    break;
135                case SetValue:
136                    block.setValue(_selectBlockValue.evaluateValue(conditionalNG));
137                    break;
138                default:
139                    throw new IllegalArgumentException("invalid oper state: " + theOper.name());
140            }
141        });
142    }
143
144    @Override
145    public FemaleSocket getChild(int index) throws IllegalArgumentException, UnsupportedOperationException {
146        throw new UnsupportedOperationException("Not supported.");
147    }
148
149    @Override
150    public int getChildCount() {
151        return 0;
152    }
153
154    @Override
155    public String getShortDescription(Locale locale) {
156        return Bundle.getMessage(locale, "ActionBlock_Short");
157    }
158
159    @Override
160    public String getLongDescription(Locale locale) {
161        String namedBean = _selectNamedBean.getDescription(locale);
162        String state = _selectEnum.getDescription(locale);
163
164        if (_selectEnum.isDirectAddressing()) {
165            if (_selectEnum.getEnum() == DirectOperation.SetValue) {
166                String bundleKey = "ActionBlock_Long_Value";
167                return Bundle.getMessage(locale, bundleKey, namedBean, _selectBlockValue.getDescription(locale));
168            }
169        }
170
171        return Bundle.getMessage(locale, "ActionBlock_Long", namedBean, state);
172    }
173
174    /** {@inheritDoc} */
175    @Override
176    public void setup() {
177        // Do nothing
178    }
179
180    /** {@inheritDoc} */
181    @Override
182    public void disposeMe() {
183    }
184
185    public enum DirectOperation {
186        SetOccupied(Bundle.getMessage("ActionBlock_SetOccupied")),
187        SetNotOccupied(Bundle.getMessage("ActionBlock_SetNotOccupied")),
188        SetAltColorOn(Bundle.getMessage("ActionBlock_SetAltColorOn")),
189        SetAltColorOff(Bundle.getMessage("ActionBlock_SetAltColorOff")),
190        SetNullValue(Bundle.getMessage("ActionBlock_SetNullValue")),
191        SetValue(Bundle.getMessage("ActionBlock_SetValue"));
192
193        private final String _text;
194
195        private DirectOperation(String text) {
196            this._text = text;
197        }
198
199        @Override
200        public String toString() {
201            return _text;
202        }
203
204    }
205
206    /** {@inheritDoc} */
207    @Override
208    public void getUsageDetail(int level, NamedBean bean, List<NamedBeanUsageReport> report, NamedBean cdl) {
209        _selectNamedBean.getUsageDetail(level, bean, report, cdl, this, LogixNG_SelectNamedBean.Type.Action);
210    }
211
212    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ActionBlock.class);
213
214}