001package jmri.jmrix.roco.z21.messageformatters;
002
003import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
004import jmri.jmrix.Message;
005import jmri.jmrix.roco.z21.Z21MessageFormatter;
006import jmri.jmrix.roco.z21.Z21MessageUtils;
007import jmri.jmrix.roco.z21.Z21Reply;
008
009/**
010 * Formats Z21 CAN Detector Replies.
011 *
012 * @author Paul Bender Copyright (C) 2025
013 */
014public class Z21CANDetectorReplyFormatter implements Z21MessageFormatter {
015
016    @Override
017    public boolean handlesMessage(Message m) {
018        return m instanceof Z21Reply && ((Z21Reply) m).getOpCode() == 0x00C4;
019    }
020
021    @Override
022    @SuppressFBWarnings(value = "SF_SWITCH_FALLTHROUGH")
023    public String formatMessage(Message m) {
024        if(!handlesMessage(m)){
025            throw new IllegalArgumentException("Message is not a Z21 CAN Detector Reply");
026        }
027        int networkID = ( m.getElement(4)&0xFF) + ((m.getElement(5)&0xFF) << 8);
028        int address = ( m.getElement(6)&0xFF) + ((m.getElement(7)&0xFF) << 8);
029        int port = ( m.getElement(8) & 0xFF);
030        int type = ( m.getElement(9) & 0xFF);
031        int value1 = (m.getElement(10)&0xFF) + ((m.getElement(11)&0xFF) << 8);
032        int value2 = (m.getElement(12)&0xFF) + ((m.getElement(13)&0xFF) << 8);
033        String typeString = "";
034        String value1String;
035        String value2String = "";
036        switch(type){
037            case 0x01:
038                typeString = "Input Status";
039                switch(value1){
040                    case 0x0000:
041                        value1String = Bundle.getMessage("Z21_CAN_INPUT_STATUS_FREE_WITHOUT");
042                        break;
043                    case 0x0100:
044                        value1String = Bundle.getMessage("Z21_CAN_INPUT_STATUS_FREE_WITH");
045                        break;
046                    case 0x1000:
047                        value1String = Bundle.getMessage("Z21_CAN_INPUT_STATUS_BUSY_WITHOUT");
048                        break;
049                    case 0x1100:
050                        value1String = Bundle.getMessage("Z21_CAN_INPUT_STATUS_BUSY_WITH");
051                        break;
052                    case 0x1201:
053                        value1String = Bundle.getMessage("Z21_CAN_INPUT_STATUS_OVERLOAD_1");
054                        break;
055                    case 0x1202:
056                        value1String = Bundle.getMessage("Z21_CAN_INPUT_STATUS_OVERLOAD_2");
057                        break;
058                    case 0x1203:
059                        value1String = Bundle.getMessage("Z21_CAN_INPUT_STATUS_OVERLOAD_3");
060                        break;
061                    default:
062                        value1String = "<unknown>";
063                }
064                break;
065            case 0x11:
066            case 0x12:
067            case 0x13:
068            case 0x14:
069            case 0x15:
070            case 0x16:
071            case 0x17:
072            case 0x18:
073            case 0x19:
074            case 0x1A:
075            case 0x1B:
076            case 0x1C:
077            case 0x1D:
078            case 0x1E:
079            case 0x1F:
080                typeString = "Occupancy Info";
081                value1String = getCanDetectorLocoAddressString(value1);
082                value2String = getCanDetectorLocoAddressString(value2);
083                break;
084            default:
085                value1String = "" + value1;
086                value2String = "" + value2;
087        }
088
089        return Bundle.getMessage("Z21CANDetectorReply",Integer.toHexString(networkID),address,port,typeString,value1String,value2String);
090    }
091
092    // address value is the 16 bits of the two bytes containing the
093    // address.  The most significan two bits represent the direction.
094    private String getCanDetectorLocoAddressString(int addressValue) {
095        String addressString;
096        if(addressValue==0) {
097            addressString="end of list";
098        } else {
099            addressString = "" + (Z21MessageUtils.getCanDetectorLocoAddress(addressValue)).toString();
100            int direction = (0xC000&addressValue);
101            switch (direction) {
102                case 0x8000:
103                    addressString += " direction forward";
104                    break;
105                case 0xC000:
106                    addressString += " direction reverse";
107                    break;
108                default:
109                    addressString += " direction unknown";
110            }
111        }
112        return addressString;
113    }
114
115}