001package jmri.jmrix.loconet.pr3;
002
003import jmri.GlobalProgrammerManager;
004import jmri.InstanceManager;
005import jmri.PowerManager;
006import jmri.ThrottleManager;
007import jmri.jmrix.loconet.LnPowerManager;
008import jmri.jmrix.loconet.LnTrafficController;
009import jmri.jmrix.loconet.LocoNetMessage;
010import jmri.jmrix.loconet.LocoNetSystemConnectionMemo;
011import jmri.jmrix.loconet.SlotManager;
012import org.slf4j.Logger;
013import org.slf4j.LoggerFactory;
014
015/**
016 * Lightweight class to denote that a PR3 is active
017 *
018 * @author Bob Jacobsen Copyright (C) 2010
019 * @author B. Milhaupt Copyright (C) 2017
020 */
021public class PR3SystemConnectionMemo extends LocoNetSystemConnectionMemo {
022
023    public PR3SystemConnectionMemo(LnTrafficController lt,
024            SlotManager sm) {
025        super(lt, sm);
026    }
027
028    public PR3SystemConnectionMemo() {
029        super();
030    }
031
032    @SuppressWarnings("unchecked")
033    @Override
034    public <T> T get(Class<T> T) {
035        if (getDisabled()) {
036            return null;
037        }
038        if (mode == MS100MODE) {
039            return super.get(T);
040        }
041        if (T.equals(jmri.GlobalProgrammerManager.class)) {
042            return (T) getProgrammerManager();
043        }
044        if (T.equals(jmri.AddressedProgrammerManager.class)) {
045            return (T) getProgrammerManager();
046        }
047
048        if (T.equals(jmri.ThrottleManager.class)) {
049            return (T) getThrottleManager();
050        }
051        if (T.equals(jmri.PowerManager.class)) {
052            return (T) getPowerManager();
053        }
054        if(T.equals(jmri.ConsistManager.class)){
055            return (T) getConsistManager();
056        }
057        return null;
058    }
059
060    final static int PR3MODE = 0x00;
061    final static int MS100MODE = 0x01;
062
063    int mode = PR3MODE;
064    private Runnable restoreToLocoNetInterfaceModeTask;
065
066    /**
067     * Configure the subset of LocoNet managers valid for the PR3 in PR2 mode.
068     */
069    public void configureManagersPR2() {
070        mode = PR3MODE;
071        log.info("Connection [{}] initialized as \"Stand Alone Programmer\", no access to attached devices. (see preferences)",getSystemPrefix());
072        InstanceManager.store(getPowerManager(), jmri.PowerManager.class);
073
074        InstanceManager.setThrottleManager(
075                getThrottleManager());
076
077        if (getProgrammerManager().isAddressedModePossible()) {
078            InstanceManager.store(getProgrammerManager(), jmri.AddressedProgrammerManager.class);
079        }
080        if (getProgrammerManager().isGlobalProgrammerAvailable()) {
081            InstanceManager.store(getProgrammerManager(), GlobalProgrammerManager.class);
082        }
083        // Establish a ShutDownTask so that the PR3 should be be returned to
084        // LocoNet Interface mode at shutdown
085        // Finally, create and register a shutdown task to ensure clean exit
086        if (restoreToLocoNetInterfaceModeTask == null) {
087            restoreToLocoNetInterfaceModeTask = () -> {
088                if (mode == PR3MODE) {
089                    // try to change from "standalone programmer" to "LocoNet interface" mode
090                    LnTrafficController tc;
091                    tc = getLnTrafficController();
092                    if (tc != null) {
093                        LocoNetMessage msg = new LocoNetMessage(6);
094                        msg.setOpCode(0xD3);
095                        msg.setElement(1, 0x10);
096                        msg.setElement(2, 0);  // set MS100, no power
097                        msg.setElement(3, 0);
098                        msg.setElement(4, 0);
099                        tc.sendLocoNetMessage(msg);
100                        log.info("Configuring PR3 for 'LocoNet Interface' mode"); // NOI18N
101                    }
102                }
103            };
104            InstanceManager.getDefault(jmri.ShutDownManager.class).register(restoreToLocoNetInterfaceModeTask);
105        }
106
107        register();
108    }
109
110    @Override
111    public ThrottleManager getThrottleManager() {
112        if (super.getDisabled()) {
113            return null;
114        }
115        if (mode == MS100MODE) {
116            return super.getThrottleManager();
117        }
118        return (ThrottleManager) classObjectMap.computeIfAbsent(ThrottleManager.class,(Class<?> c) -> new jmri.jmrix.loconet.LnPr2ThrottleManager(this));
119    }
120
121    @Override
122    public boolean provides(Class<?> type) {
123        if (getDisabled()) {
124            return false;
125        }
126        if (mode == MS100MODE) {
127            return super.provides(type);
128        }
129        if (type.equals(jmri.GlobalProgrammerManager.class)) {
130            return getProgrammerManager().isGlobalProgrammerAvailable();
131        }
132        if (type.equals(jmri.AddressedProgrammerManager.class)) {
133            return getProgrammerManager().isAddressedModePossible();
134        }
135
136        if (type.equals(jmri.ThrottleManager.class)) {
137            return true;
138        }
139        if (type.equals(jmri.PowerManager.class)) {
140            return true;
141        }
142        if(type.equals(jmri.ConsistManager.class)){
143           return(getConsistManager()!=null);
144        }
145        return false;
146    }
147    //private jmri.jmrix.loconet.pr2.LnPr2PowerManager powerManager;
148
149    /**
150     * Get the connection's LnPowerManager.
151     *
152     * @return the LocoNet power manager; may be null in some circumstances
153     */
154    @Override
155    public LnPowerManager getPowerManager() {
156        if (getDisabled()) {
157            return null;
158        }
159        if (mode == MS100MODE) {
160            return super.getPowerManager();
161        }
162        return (LnPowerManager) classObjectMap.computeIfAbsent(PowerManager.class,(Class<?> c) -> new jmri.jmrix.loconet.pr2.LnPr2PowerManager(this));
163    }
164
165    /**
166     * Configure the LocoNet managers valid for the PR3 in MS100 mode, same as super, flag the interface type.
167     */
168    public void configureManagersMS100() {
169        mode = MS100MODE;
170        log.info("Connection [{}] initialized as LocoNet interface, allows access to attached devices. (see preferences)",getSystemPrefix());
171        super.configureManagers();
172    }
173
174    @Override
175    public void dispose() {
176        InstanceManager.deregister(this, PR3SystemConnectionMemo.class);
177        if(tm!=null){
178           tm.dispose();
179        }
180        super.dispose();
181    }
182
183    private final static Logger log = LoggerFactory.getLogger(PR3SystemConnectionMemo.class);
184
185}