<?php

class TrackingStatus {

    public const TRACKING_STATUS_UNKNOWN = 0;
    public const TRACKING_STATUS_PRE_TRANSIT = 1;
    public const TRACKING_STATUS_TRANSIT = 2;
    public const TRACKING_STATUS_DELIVERED = 3;
    public const TRACKING_STATUS_RETURNED = 4;
    public const TRACKING_STATUS_FAILURE = 5;
    public const TRACKING_STATUS_INFO = 6;

    /**
     * Convert a status string API response to a constant integer.
     * @param string $status
     * @return int
     */
    public static function stringToStatus(string $status): int {
        $status = strtoupper($status);
        switch ($status) {
            case "PRE_TRANSIT":
                return TrackingStatus::TRACKING_STATUS_PRE_TRANSIT;
            case "TRANSIT":
            case "IN_TRANSIT":
            case "ACCEPTED":
            case "OUT_FOR_DELIVERY":
                return TrackingStatus::TRACKING_STATUS_TRANSIT;
            case "DELIVERED":
                return TrackingStatus::TRACKING_STATUS_DELIVERED;
            case "AVAILABLE_FOR_PICKUP":
            case "CANCELLED":
                return TrackingStatus::TRACKING_STATUS_INFO;
            case "RETURNED":
            case "RETURN_TO_SENDER":
                return TrackingStatus::TRACKING_STATUS_RETURNED;
            case "FAILURE":
            case "DELIVERY ATTEMPT":
            case "ALERT":
            case "ERROR":
                return TrackingStatus::TRACKING_STATUS_FAILURE;
            default:
                return TrackingStatus::TRACKING_STATUS_UNKNOWN;
        }
    }

    /**
     * Convert a status constant to a string.
     * @param int $status
     * @return string
     */
    public static function statusToString(int $status): string {
        switch ($status) {
            case TrackingStatus::TRACKING_STATUS_PRE_TRANSIT:
                return "PRE_TRANSIT";
            case TrackingStatus::TRACKING_STATUS_TRANSIT:
                return "TRANSIT";
            case TrackingStatus::TRACKING_STATUS_DELIVERED:
                return "DELIVERED";
            case TrackingStatus::TRACKING_STATUS_RETURNED:
                return "RETURNED";
            case TrackingStatus::TRACKING_STATUS_FAILURE:
                return "FAILURE";
            case TrackingStatus::TRACKING_STATUS_INFO:
                return "INFO";
            default:
                return "UNKNOWN";
        }
    }

    /**
     * Returns false if a two-char USPS API scan event is probably a physical scan of the actual item
     * @param string $eventcode
     * @return boolean
     */
    public static function isUSPSEventCodeContainerScan(string $eventcode) {
        switch ($eventcode) {
            case "A1":
            case "AE":
            case "DE":
            case "E1":
            case "L1":
            case "MA":
            case "MR":
            case "NT":
            case "OA":
            case "OD":
            case "OF":
            case "OX":
            case "PC":
            case "RB":
            case "SF":
            case "T1":
            case "TM":
            case "TX":
            case "U1":
            case "UA":
            case "VF":
            case "VR":
            case "WX":
            case "GX":
            case "80":
            case "89":
                return true;
            default:
                return false;
        }
    }

    public static function USPSEventCodeToStatus(string $eventcode) {
        switch ($eventcode) {
            case "GC":
            case "GX":
            case "MA":
            case "89":
                return TrackingStatus::TRACKING_STATUS_PRE_TRANSIT;
            case "03":
            case "06":
            case "07":
            case "08":
            case "10":
            case "12":
            case "PA":
            case "14":
            case "15":
            case "16":
            case "17":
            case "19":
            case "30": // no access
            case "34":
            case "35":
            case "36":
            case "38":
            case "39":
            case "40":
            case "42":
            case "45":
            case "52":
            case "58":
            case "59":
            case "70":
            case "71":
            case "72":
            case "73":
            case "74":
            case "80":
            case "81":
            case "82":
            case "83":
            case "A1":
            case "AD":
            case "AE":
            case "AR":
            case "AX":
            case "B1":
            case "B5":
            case "BB":
            case "DD":
            case "DE":
            case "DX":
            case "E1":
            case "EF":
            case "L1":
            case "MR":
            case "NT": // generic filler messages to fill tracking gaps
            case "NP":
            case "C0":
            case "U1":
            case "OA":
            case "OD":
            case "OF":
            case "PC":
            case "RB":
            case "RC":
            case "SF":
            case "T1":
            case "TM":
            case "UA":
            case "VF":
            case "VR":
            case "WX":
            case "AP":
            case "AT": // departed a transfer airport (int'l)
            case "A0": // "Acceptance" from foreign country
            case "B0": // "Processed Through Facility" (int'l)
            case "CO": // "Inbound Out of Customs"
            case "D0": // "Processed Through Facility" (int'l)
            case "G0": // "Arrival at Post Office" (int'l)
            case "MF": // "Processed through Facility" (int'l)
            case "DG": // "Out for Delivery" (int'l)
            case "TL": // "moving within the USPS network" filler message
            case "AH": // int'l something or other
            case "B3": // Released from U.S. customs
                return TrackingStatus::TRACKING_STATUS_TRANSIT;
            case "CI": // stuck in customs
            case "ME": // "Held in Customs" (int'l, isn't necessarily bad)
            case "LD": // letter estimated to be delivered today
            case "E0": // "Customs Clearance" (int'l)
            case "F0": // "Customs Clearance Processing Complete" (int'l)
                return TrackingStatus::TRACKING_STATUS_INFO;
            case "01":
            case "13":
            case "17":
            case "41":
            case "43":
            case "60":
            case "61":
            case "62":
            case "63":
            case "84":
            case "85":
            case "86":
            case "87":
            case "I0": // International something or other
                return TrackingStatus::TRACKING_STATUS_DELIVERED;
            case "04":
            case "05":
            case "09":
            case "21":
            case "22":
            case "23":
            case "24":
            case "25":
            case "26":
            case "27":
            case "28":
            case "29":
                return TrackingStatus::TRACKING_STATUS_RETURNED;
            case "02":
            case "53":
            case "54":
            case "55":
            case "56":
            case "57":
            case "64":
            case "04":
            case "05":
            case "11":
            case "16":
            case "31":
            case "32":
            case "33":
            case "44":
            case "51":
            case "LX": // LOOP bin
            case "OX":
            case "TX":
                return TrackingStatus::TRACKING_STATUS_FAILURE;
            default:
                file_put_contents(__DIR__ . "/usps_unknown_events.log", "$eventcode\n", FILE_APPEND);
                return TrackingStatus::TRACKING_STATUS_UNKNOWN;
        }
    }

    public static function UPSEventTypeToStatus(string $eventcode) {
        switch ($eventcode) {
            case "M":
            case "MV":
                return TrackingStatus::TRACKING_STATUS_PRE_TRANSIT;
            case "ZA": // UPS My Choice redirect
                return TrackingStatus::TRACKING_STATUS_INFO;
            case "I":
            case "P":
            case "O":
            case "W":
            case "DO":
            case "DD":
                return TrackingStatus::TRACKING_STATUS_TRANSIT;
            case "D":
                return TrackingStatus::TRACKING_STATUS_DELIVERED;
            case "RS":
                return TrackingStatus::TRACKING_STATUS_RETURNED;
            case "X":
                return TrackingStatus::TRACKING_STATUS_FAILURE;
            case "NA":
            default:
                return TrackingStatus::TRACKING_STATUS_UNKNOWN;
        }
    }

    public static function FedExEventTypeToStatus(string $eventcode) {
        switch ($eventcode) {
            case "OC":
            case "OX":
            case "PD":
            case "RP":
            case "RG":
            case "SH":
                return TrackingStatus::TRACKING_STATUS_PRE_TRANSIT;
            case "AA":
            case "AC":
            case "AD":
            case "AF":
            case "AO":
            case "AP":
            case "AR":
            case "AX":
            case "CH":
            case "DD":
            case "DP":
            case "DR":
            case "DS":
            case "EA":
            case "ED":
            case "EO":
            case "EP":
            case "FD":
            case "HL":
            case "IT":
            case "IX":
            case "LO":
            case "OD":
            case "OF":
            case "PF":
            case "PL":
            case "PM":
            case "PU":
            case "PX":
            case "SF":
            case "TR":
            case "CC":
            case "CD":
            case "CP":
            case "EA":
            case "CA":
            case "CU":
            case "BR":
            case "TP":
            case "IP":
            case "DO": // dropped off
                return TrackingStatus::TRACKING_STATUS_TRANSIT;
            case "AE": // Arriving early
            case "AS": // Address corrected
            case "HP": // Ready for pickup
            case "RR": // Delivery change (redirect/hold for pickup) request submitted
                return TrackingStatus::TRACKING_STATUS_INFO;
            case "RC": // Recipient
            case "DL": // Delivered
                return TrackingStatus::TRACKING_STATUS_DELIVERED;
            case "RS":
                return TrackingStatus::TRACKING_STATUS_RETURNED;
            case "CA":
            case "DE":
            case "DY":
            case "LP":
            case "RD":
            case "SE":
                return TrackingStatus::TRACKING_STATUS_FAILURE;
            case "SP":
            default:
                return TrackingStatus::TRACKING_STATUS_UNKNOWN;
        }
    }
}
