<?php

class Tracking_Shippo {

    /**
     *
     * @param string $code
     * @return \TrackingInfo
     * @throws TrackingException
     */
    public static function track(string $code, string $carrier = ""): TrackingInfo {
        $barcode = new TrackingBarcode($code);

        Shippo::setApiKey(env("shippo_key"));

        try {
            $status = Shippo_Track::get_status([
                        "id" => $code,
                        "carrier" => empty($carrier) ? Carriers::getCarrierCode($barcode->getCarrier()) : $carrier
            ]);
        } catch (Exception $ex) {
            throw new TrackingException("There was a server problem. This code cannot be tracked right now.");
        }

        if (empty($status->tracking_status) && empty($status->address_to) && empty($status->address_from)) {
            throw new TrackingException("Unknown tracking code (best guess: " . Carriers::getCarrierName($barcode->getCarrier()) . ").");
        }

        $info = new TrackingInfo();

        $info->setCode($barcode->getCode());
        $info->setCarrier($barcode->getCarrier());
        $info->setService(new Service($status->servicelevel->token, $status->servicelevel->name));
        $info->setCarrierAttributionText(CarrierAssets::getAttribution(Carriers::getCarrierCode($info->getCarrier())));
        $info->setCarrierLogo(CarrierAssets::getLogo(Carriers::getCarrierCode($info->getCarrier())));

        if (!empty($status->tracking_status)) {
            $current_status = new TrackingEntry(
                    TrackingStatus::stringToStatus($status->tracking_status->status),
                    $status->tracking_status->status_details,
                    $status->tracking_status->status_date
            );

            if (!empty($status->tracking_status->location)) {
                $current_location = new Location();
                $current_location->city = $status->tracking_status->location->city;
                $current_location->state = $status->tracking_status->location->state;
                $current_location->zip = $status->tracking_status->location->zip;
                $current_location->country = $status->tracking_status->location->country;
                $current_status->setLocation($current_location);
            }

            $info->setCurrentStatus($current_status);
        }

        if (!empty($status->address_from)) {
            $from = new Location();
            $from->city = empty($status->address_from->city) ? "" : $status->address_from->city;
            $from->state = empty($status->address_from->state) ? "" : $status->address_from->state;
            $from->zip = empty($status->address_from->zip) ? "" : $status->address_from->zip;
            $from->country = empty($status->address_from->country) ? "" : $status->address_from->country;

            $info->setFrom($from);
        }

        if (!empty($status->address_to)) {
            $to = new Location();
            $to->city = empty($status->address_to->city) ? "" : $status->address_to->city;
            $to->state = empty($status->address_to->state) ? "" : $status->address_to->state;
            $to->zip = empty($status->address_to->zip) ? "" : $status->address_to->zip;
            $to->country = empty($status->address_to->country) ? "" : $status->address_to->country;

            $info->setTo($to);
        }

        foreach ($status->tracking_history as $history) {
            $location = new Location();
            $location->city = $history->location["city"];
            $location->state = $history->location["state"];
            $location->zip = $history->location["zip"];
            $location->country = $history->location["country"];
            $info->appendHistoryEntry(new TrackingEntry(TrackingStatus::stringToStatus($history->status), $history->status_details, $history->status_date, $location));
        }

        return $info;
    }

}
