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) {
035        if (getDisabled()) {
036            return null;
037        }
038        if (mode == MS100MODE) {
039            return (T) 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        InstanceManager.store(getPowerManager(), jmri.PowerManager.class);
072
073        InstanceManager.setThrottleManager(
074                getThrottleManager());
075
076        if (getProgrammerManager().isAddressedModePossible()) {
077            InstanceManager.store(getProgrammerManager(), jmri.AddressedProgrammerManager.class);
078        }
079        if (getProgrammerManager().isGlobalProgrammerAvailable()) {
080            InstanceManager.store(getProgrammerManager(), GlobalProgrammerManager.class);
081        }
082        // Establish a ShutDownTask so that the PR3 should be be returned to
083        // LocoNet Interface mode at shutdown
084        // Finally, create and register a shutdown task to ensure clean exit
085        if (restoreToLocoNetInterfaceModeTask == null) {
086            restoreToLocoNetInterfaceModeTask = () -> {
087                if (mode == PR3MODE) {
088                    // try to change from "standalone programmer" to "LocoNet interface" mode
089                    LnTrafficController tc;
090                    tc = getLnTrafficController();
091                    if (tc != null) {
092                        LocoNetMessage msg = new LocoNetMessage(6);
093                        msg.setOpCode(0xD3);
094                        msg.setElement(1, 0x10);
095                        msg.setElement(2, 0);  // set MS100, no power
096                        msg.setElement(3, 0);
097                        msg.setElement(4, 0);
098                        tc.sendLocoNetMessage(msg);
099                        log.info("Configuring PR3 for 'LocoNet Interface' mode"); // NOI18N
100                    }
101                }
102            };
103            InstanceManager.getDefault(jmri.ShutDownManager.class).register(restoreToLocoNetInterfaceModeTask);
104        }
105    }
106
107    @Override
108    public ThrottleManager getThrottleManager() {
109        if (super.getDisabled()) {
110            return null;
111        }
112        if (mode == MS100MODE) {
113            return super.getThrottleManager();
114        }
115        return (ThrottleManager) classObjectMap.computeIfAbsent(ThrottleManager.class,(Class c) -> new jmri.jmrix.loconet.LnPr2ThrottleManager(this));
116    }
117
118    @Override
119    public boolean provides(Class<?> type) {
120        if (getDisabled()) {
121            return false;
122        }
123        if (mode == MS100MODE) {
124            return super.provides(type);
125        }
126        if (type.equals(jmri.GlobalProgrammerManager.class)) {
127            return getProgrammerManager().isGlobalProgrammerAvailable();
128        }
129        if (type.equals(jmri.AddressedProgrammerManager.class)) {
130            return getProgrammerManager().isAddressedModePossible();
131        }
132
133        if (type.equals(jmri.ThrottleManager.class)) {
134            return true;
135        }
136        if (type.equals(jmri.PowerManager.class)) {
137            return true;
138        }
139        if(type.equals(jmri.ConsistManager.class)){
140           return(getConsistManager()!=null);
141        } 
142        return false;
143    }
144    //private jmri.jmrix.loconet.pr2.LnPr2PowerManager powerManager;
145
146    /**
147     * Get the connection's LnPowerManager.
148     *
149     * @return the LocoNet power manager; may be null in some circumstances
150     */
151    @Override
152    public LnPowerManager getPowerManager() {
153        if (getDisabled()) {
154            return null;
155        }
156        if (mode == MS100MODE) {
157            return super.getPowerManager();
158        }
159        return (LnPowerManager) classObjectMap.computeIfAbsent(PowerManager.class,(Class c) -> new jmri.jmrix.loconet.pr2.LnPr2PowerManager(this));
160    }
161
162    /**
163     * Configure the LocoNet managers valid for the PR3 in MS100 mode, same as super, flag the interface type.
164     */
165    public void configureManagersMS100() {
166        mode = MS100MODE;
167        super.configureManagers();
168    }
169
170    @Override
171    public void dispose() {
172        InstanceManager.deregister(this, PR3SystemConnectionMemo.class);
173        if(tm!=null){
174           tm.dispose();
175        }
176        super.dispose();
177    }
178
179    private final static Logger log = LoggerFactory.getLogger(PR3SystemConnectionMemo.class);
180
181}