// Decode decodes an array of bytes into an object.
//  - fPort contains the LoRaWAN fPort number
//  - bytes is an array of bytes, e.g. [225, 230, 255, 0]
//  - variables contains the device variables e.g. {"calibration": "3.5"} (both the key / value are of type string)
// The function must return an object, e.g. {"temperature": 22.5}
// for Yunhorn SmarToilets STS-O7 Occupancy/Fall Detection/Over stay sensor
function Decode(fPort, data, variables) {
    var data = {};
    if ((fPort === 17) || (fPort === 19) || (fPort === 21)) {
        data.BoardLED = bytes[0] & 0x7F;
        switch (bytes[1]) {
            case 0x00:
                data.LEDcolor = "Dark";
                break;
            case 0x01:
                data.LEDcolor = "Green";
                data.cubicleOccupyStatus = "Vacant";
                break;
            case 0x02:
                data.LEDcolor = "Red";
                data.cubicleOccupyStatus = "Occupied";
                break;
            case 0x03:
                data.LEDcolor = "Blue";
                data.cubicleOccupyStatus = "Maintenance";
                break;
            case 0x04:
                data.LEDcolor = "Yellow";
                data.cubicleOccupyStatus = "TBD";
                break;
            case 0x05:
                data.LEDcolor = "Pink";
                data.cubicleOccupyStatus = "TBD";
                break;
            case 0x06:
                data.LEDcolor = "Cyan";
                data.cubicleOccupyStatus = "TBD";
                break;
            case 0x07:
                data.LEDcolor = "White";
                data.cubicleOccupyStatus = "TBD";
                break;
            case 0x08:
                data.LEDcolor = "Red_Blue";
                data.cubicleOccupyStatus = "EMERGENCY";
                break;
            case 0x23:
                data.LEDcolor = "Red_Blue";
                data.cubicleOccupyStatus = "EMERGENCY";
                break;
            case 0x20:
                data.LEDcolor = "Red_Flash";
                data.cubicleOccupyStatus = "EMERGENCY";
                break;
            default:
                data.LEDcolor = "TBD_COLOR";
                data.cubicleOccupyStatus = "TBD_status";
                break;
        }

        switch (bytes[2]) {
            case 0x0:
                data.workmode = "Network_mode";
                break;
            case 0x01:
                data.workmode = "Wired_Mode";
                break;
            case 0x02:
                data.workmode = "Hall_element_mode";
                break;
            case 0x03:
                data.workmode = "MotionDetect_mode";
                break;
            case 0x04:
                data.workmode = "Dual_mode";
                break;
            case 0x05:
                data.workmode = "Uni_Mode";
                break;
            default:
                data.workmode = "Unknown Mode";
                break;
        }

        data.Sensor1_Door_Contact_Open = bytes[3] === 0 ? "Door Closed" : "Door Open";
        data.Sensor2_Motion_Detected = bytes[4] === 0 ? "No Motion" : "Motion Detected";
        data.Sensor3_Emergency_Button = bytes[5] === 0 ? "Alarm Push Down" : "No Alarm, Released";
        if (bytes.length > 6) {
            data.Sensor4 = bytes[6] === 0 ? "No" : "Yes";
            data.Distance_in_mm = (bytes[7] << 8 | bytes[8]);
            data.MotionLevel = (bytes[9] << 8 | bytes[10]);

            data.Unconcious_State = bytes[11];
            switch (bytes[12]) {
                case 0x0:
                    data.Fall_Down_Detected_State = "Presence_None";
                    break;
                case 0x01:
                    data.Fall_Down_Detected_State = "Presence_Fall_Down";
                    break;
                case 0x02:
                    data.Fall_Down_Detected_State = "Presence_Rising_Up";
                    break;
                case 0x03:
                    data.Fall_Down_Detected_State = "Presence_LayDown";
                    break;
                case 0x04:
                    data.Fall_Down_Detected_State = "Presence_Unconcious";
                    break;
                case 0x05:
                    data.Fall_Down_Detected_State = "Presence_Stay_Still";
                    break;
            }
            data.OverStay_Detected_State = (bytes[13] == 0x0) ? "No" : "Yes";
            data.OverStay_Duration_in_Seconds = (bytes[14] << 8 | bytes[15]);
        }
        return { "Yunhorn_SmarToilets_data": data };
    }
    // Heart Beat 
    else if (fPort === 20) {
        var data = {};
        data.led_state = (bytes[0] & 0x7f) === 0 ? "Off" : "On";
        data.battery_level = bytes[1] + " %";
        return { "Yunhorn_SmarToilets_data": data };
    }

    // UPLINK, RFAC
    else if (fPort === 1) {
        var data = {};
        data.length = bytes.length;

        if (data.length === 4) {
            data.RFAC = "OK";
            data.AC0 = bytes[0];
            data.AC1 = bytes[1];
        }


        if ((bytes[0] === 0x59) && (bytes[1] === 0x44)) {
            data.Heart_beat_Duration = (bytes[2] - 0x30) * 10 + (bytes[3] - 0x30);
            data.Unit = String.fromCharCode(bytes[4]);
        }
        else if ((bytes[0] === 0x59) && (bytes[1] === 0x53)) {
            data.Wakeup_sampling_interval = (bytes[2] - 0x30) * 10 + (bytes[3] - 0x30);
            data.Unit = String.fromCharCode(bytes[4]);
        }

        else if (bytes[0] === 0x53) {  // SELF TEST FUNCTION
            data.mtm_code1 = bytes[1];
            data.mtm_code2 = bytes[2];
            data.sts_verion = bytes[3];
            data.sts_hw_ver = bytes[4];
            data.battery_level = bytes[5];
            data.sts_test_result_length = bytes[6];
            data.sts_rss_sub_code1 = bytes[7];
            data.sts_rss_sub_code2 = bytes[8];
            data.sts_rss_sub_code3 = bytes[9];
            data.sts_rss_sub_code4 = bytes[10];
            data.sts_rss_sub_code5 = bytes[11];
            data.sts_rss_sub_code6 = bytes[12];
            data.sts_rss_sub_code7 = bytes[13];
            data.sts_rss_sub_code8 = bytes[14];
            data.sts_rss_sub_code9 = bytes[15];
            data.sts_rss_sub_code10 = bytes[16];
            data.sts_sensor_install_height = String.fromCharCode(bytes[17]) + String.fromCharCode(bytes[18]) + String.fromCharCode(bytes[19]) + String.fromCharCode(bytes[20]) + " mm";
        }
        else if (bytes[0] === 0x56) {

            data.mtm_code1 = bytes[1];
            data.mtm_code2 = bytes[2];
            data.sts_verion = bytes[3];
            data.sts_hw_ver = bytes[4];
            data.sts_major = bytes[5];
            data.sts_minor = bytes[6];
            data.subminor = bytes[7];

            if (data.length === 15) {
                data.L_year = (bytes[8] << 8 | bytes[9]);
                data.L_mon = bytes[10];
                data.L_day = bytes[11];
                data.L_hour = bytes[12];
                data.L_min = bytes[13];
                data.L_sec = bytes[14];
                data.LocalTime_UTC = "UTC:  " + data.L_year + "/" + data.L_mon + "/" + data.L_day + " " + data.L_hour + ":" + data.L_min + ":" + data.L_sec;
                data.LocalTime_EST8 = "GMT+8: " + data.L_year + "/" + data.L_mon + "/" + data.L_day + " " + (data.L_hour + 8) + ":" + data.L_min + ":" + data.L_sec;
            }
        }
        return { "Yunhorn_SmarToilets_data": data };
    }
}