<?php

class ActivityDirectApi extends Api
{
    public $apiName = 'activitydirect';

    public function indexAction()
    {
        return $this->response(
            array(
                'error' => 'Data not found'
            ), 404);
    }

    /**
     * Method GET
     * Get single record (by id)
     * http://DOMAIN/trips/1
     * @return string
     */
    public function viewAction()
    {
        return $this->response(
            array(
                'error'=> 'Data not found'
            ), 404);
    }

    public function createAction()
    {
        syslog(LOG_WARNING,'ActivityDirectApi::createAction()');
        $message = 'No recent activity found';
        $code = 404;
        $time = $this->requestParams['time'] ?? '';
        $location = $this->requestParams['location'] ?? [];
        $country = $this->requestParams['country'] ?? ActivityDirect::DEFAULT_COUNTRY;
        $member_id = $this->requestParams['member_id'] ?? 0;
        try {
            syslog(LOG_WARNING,'country='.$country);
            $db = new Db();

            $country = Geocode::mockGPSCountry($db->getConnect(), $member_id, $country, 'default');

            if ($country!='US' && $country!='SG') {
                throw new RuntimeException('Trips has not yet launched in your country. You can still track your travel activity and access exclusive deals. Start exploring!',500);

            }
            if ($member_id<1) {
                throw new RuntimeException('Invalid member ID',500);
            }
            if ($time=='' || strtotime($time)<ActivityDirect::TIME_LIMIT) { 
                throw new RuntimeException('Invalid time',500);
            }
            $address = NULL;
            $street_address = "";
            if (is_array($location) && isset($location["lat"]) && isset($location["lng"])) {
                // DEBUG
                list($location["lat"],$location["lng"]) = Geocode::mockGPSLocation(
                    $db->getConnect(), $member_id, $location["lat"], $location["lng"], 'default');
                
                syslog(LOG_WARNING,"lat=".$location["lat"].",lng=".$location["lng"]);
                list($street_address,$err) = GeocodeApi::reverseGeocode($db, $location["lat"], $location["lng"]);
                if ($street_address=="") {
                    syslog(LOG_WARNING,'Reverse geocoder failed for ('.$location["lat"].', '.$location["lng"].')');
                    throw new RuntimeException($err?"Geocoder failed: $err":'Cannot geocode your GSP location',500);
                }
                syslog(LOG_WARNING,"street_address=".json_encode($street_address));
                list($address,$err) = Geocode::checkLatLngByAddress($db->getConnect(), $street_address, $country);
                if (!is_array($address) || !isset($address["address"])) {
                    syslog(LOG_WARNING,'Geocoder failed for "'.$street_address.'"');
                    throw new RuntimeException($err?"Geocoder failed: $err":'Cannot get address for your GPS location',500);
                }
                syslog(LOG_WARNING,json_encode($address));
            }
            // Step 1. Get activities
            list($res,$err) = ActivityDirect::getActivity(
                $db->getConnect(), $db->getConnectGPS(), $member_id,
                $location["lat"], $location["lng"], ActivityDirect::ACTIVITY_RADIUS,
                $time, ActivityDirect::TIME_DELTA, $country);
            if (!$res || count($res)<1) {
                if ($err!="") {
                    throw new RuntimeException($err, 500);
                }
                throw new RuntimeException('No recent activity found', 404);
            }
            syslog(LOG_WARNING,'Recent activity has '.count($res).' trips!');
            //ActivityDirectApi::debugTrips($res,'0');
            $destination_cache = [];
            $result = [];
            $i = 0;
            foreach ($res as $trip) {
                //ActivityDirectApi::debugTrips([$trip],'1');  
                $trip['mode'] = 'rideshare';
                $trip['steps'] = [];
                $advice = [
                    "trip"=>$trip,
                    "scooter"=>[],
                    "multimodal"=>[],
                    "rideshare"=>$trip,
                    "faster"=>NULL,
                    "cheaper"=>NULL
                ];
                //ActivityDirectApi::debugTrips([$advice],'2');
                if ($advice && count($advice)>0) {
                    $result[] = $advice;
                    $i++;
                }
                if ($i>=ActivityDirect::DEFAULT_OPTIONS) {
                    break;
                }
            }
            //syslog(LOG_WARNING,json_encode($result));
            //ActivityDirectApi::debugTrips($result,'3');
            //$result = self::processQuotesTrips($db, $member_id, $country, $result);
            //ActivityDirectApi::debugTrips($result,'4');
            //$result = self::processGojekOption($db, $member_id, $country, $result);
            //ActivityDirectApi::debugTrips($result,'5');
            //syslog(LOG_WARNING,json_encode($result));
            return $this->response(
                array(
                    "trips" => $result,
                    "street_address" => html_entity_decode($street_address)
                ), 200);
        } catch (RuntimeException $e) {
            $message = $e->getMessage();
            $code = $e->getCode();
            syslog(LOG_WARNING,$message);
        }
        return $this->response(
            array(
                "error" => $message
            ), $code);
    }

    public static function debugTrips($trips,$what='0') {
        return; /*
        foreach ($trips as $trip) {
            $leg_fare = $trip['multimodal']['options']['leg_fare'];
            syslog(LOG_WARNING,'>>>>>>> '.$what.' >>>>>>> '.json_encode($leg_fare));
        }*/
    }

    public function updateAction()
    {
        return $this->response(
            array(
                "error" => "Update error"
            ), 400);
    }

    public function deleteAction()
    {
        return $this->response(
            array(
                "error" => "Delete error"
            ), 500);
    }

    protected function checkCache($trip, $cache) {
        syslog(LOG_WARNING,'ActivityDirectApi::checkCache()');
        foreach ($cache as $item) {
            if ($item["id"]>0 && $item["id"]==$trip["id"]) {
                return [false, $cache];
            }
            if ($item["location_end_id"]==$trip["location_end_id"]) {
                return [false, $cache];
            }
        }
        $cache[] = $trip;
        return [true, $cache];
    }

    public static function processGojekOption($db, $member_id, $country, $trips) {
        syslog(LOG_WARNING,"ActivityDirectApi::processGojekOption(\$db, $member_id, $country, \$trips)");
        //"trips"=>$trips;
        if (!is_array($trips) && count($trips)<1) {
            syslog(LOG_WARNING,"Invalid trips!");
            return $trips; // No idea how to handle it
        }
        $trip = $trips[0];
        if (!array_key_exists('trip',$trip) || !is_array($trip['trip']) || count($trip['trip'])<10) {
            syslog(LOG_WARNING,"Invalid trip[0]!");
            return $trips; // No idea how to handle it
        }
        $oldTrip = $trip['trip'];
        $newTrip = [
            'cheaper' => [],
            'faster' => [],
            'multimodal' => [],
            'rideshare' => [],
            'scooter' => [],
            'trip' => $trip['trip']
        ];
        $origin = Address::getAddressById($db->getConnect(), $oldTrip['location_start_id']);
        $destination = Address::getAddressById($db->getConnect(), $oldTrip['location_end_id']);
        list($res, $err) = GeocodeApi::route($db, 
            $origin['latitude'], $origin['longitude'], 
            $destination['latitude'], $destination['longitude'], 'driving'
        );
        if ($err!=NULL || !is_array($res) || !isset($res["routes"]) || count($res["routes"])<1) {
            syslog(LOG_WARNING,'No available routes!');
            syslog(LOG_WARNING,$err);
            return $trips; // We cannot route driving!
        }
        $route_overlay = [];
        $travel_time = PHP_INT_MAX;
        $travel_distance = PHP_INT_MAX;
        foreach ($res["routes"] as $route) {
            $r = GeocodeApi::processRoute($route);
            if ($travel_time>$r['duration']) {
                $travel_time = $r['duration'];
                $travel_distance = $r['distance'];
            } 
            $route_overlay[] = $r;
        }
        $oldTrip["duration"] = $travel_time==PHP_INT_MAX ? NULL : $travel_time;
        $oldTrip["distance"] = $travel_distance==PHP_INT_MAX ? NULL : $travel_distance;
        /*
            $result = [
            'polyline' => array(), 
            'distance' => NULL, 
            'duration' => NULL, 
            'summary' => $route["summary"], 
            'overview_polyline' => $route["overview_polyline"],
            'bounds' => $route["bounds"]
        ];
        */
        //syslog(LOG_WARNING,json_encode($res));
        $route = $res["routes"][0];
        $route_leg = $route["legs"][0];
        $route_leg_steps = $route_leg["steps"];
        $overview_polyline = $route["overview_polyline"]["points"];

        $leg_steps = [];
        $distance = 0;
        $duration = 0;
        $location_start_lat = 0;
        $location_start_lng = 0;
        $location_end_lat = 0;
        $location_end_lng = 0;
        $polyline = [];
        $i = 0; $j=1; $n = count($route_leg_steps);
        for (; $i<$n; $i++) {
            $step = $route_leg_steps[$i];
            if ($step["travel_mode"] == "DRIVING") {
                $location_start_lat = $step["start_location"]["lat"];
                $location_start_lng = $step["start_location"]["lng"];
                break;
            }
            $leg_steps[] = [
                'distance' => $step["distance"]["value"],
                'duration' => $step["duration"]["value"],
                'html_instructions' => $step["html_instructions"],
                'location_end_lat' => $step["end_location"]["lat"],
                'location_end_lng' => $step["end_location"]["lng"],
                'location_start_lat' => $step["start_location"]["lat"],
                'location_start_lng' => $step["start_location"]["lng"],
                'polyline' => $step["polyline"]["points"], /*"yz|Fm_nxRi@e@_@P",*/
                'sid' => $j++,
                'travel_mode' => $step["travel_mode"]
            ];
        }
        for (;$i<$n; $i++) {
            $step = $route_leg_steps[$i];
            if ($step["travel_mode"] != "DRIVING") {
                break;
            }
            $distance += $step["distance"]["value"];
            $duration += $step["duration"]["value"];
            $location_end_lat = $step["end_location"]["lat"];
            $location_end_lng = $step["end_location"]["lng"];
            $polyline[] = $step["polyline"]["points"];
        }
        $leg_steps[] = [
            'distance' => $distance,
            'duration' => $duration,
            'fare_quote' => null,
            'fare_raw' => null,
            'html_instructions' => "Take Gojek to ".$destination["address"],
            'location_end_lat' => $location_end_lat,
            'location_end_lng' => $location_end_lng,
            'location_start_lat' => $location_start_lat,
            'location_start_lng' => $location_start_lng,
            'polyline' => MultiModal::processPolyline($polyline),
            'quote_group_id' => null,
            'sid' => $j++,
            'travel_mode' => "GOJEK"
        ];
        for (;$i<$n; $i++) {
            $step = $route_leg_steps[$i];
            $leg_steps[] = [
                'distance' => $step["distance"]["value"],
                'duration' => $step["duration"]["value"],
                'html_instructions' => $step["html_instructions"],
                'location_end_lat' => $step["end_location"]["lat"],
                'location_end_lng' => $step["end_location"]["lng"],
                'location_start_lat' => $step["start_location"]["lat"],
                'location_start_lng' => $step["start_location"]["lng"],
                'polyline' => $step["polyline"]["points"], /*"yz|Fm_nxRi@e@_@P",*/
                'sid' => $j++,
                'travel_mode' => $step["travel_mode"]
            ];
        }
        $rideshare = [
            'cost' => 1,
            'cost_raw' => 1,
            'count' => 1,
            'country' => $country,
            'distance' => $oldTrip['distance'],
            'dup_id' => null,
            'duration' => $oldTrip['duration'],
            'id' => $oldTrip['id'],
            'location_end' => $destination['address'],
            'location_end_id' => $oldTrip['location_end_id'],
            'location_end_lat' => $destination['latitude'],
            'location_end_lng' => $destination['longitude'],
            'location_end_tz' => $destination['timezone'],
            'location_start' => $origin['address'],
            'location_start_id' => $oldTrip['location_start_id'],
            'location_start_lat' => $origin['latitude'],
            'location_start_lng' => $origin['longitude'],
            'location_start_tz' => $origin['timezone'],
            'member_id' => $member_id,
            'options' => [],
            'parsedemail_item_id' => null, /* $trip['id'] ??? */
            'private' => 't',
            'scheduled' => null,
            'trackedemail_item_id' => null,
            'transport_provider_id' => null,
            'travel_date' => $oldTrip['travel_date'],
            'travel_date_end' => $oldTrip['travel_date_end'],
            'updated' => $oldTrip['updated']
        ];
        $leg_id = rand(1,10000);
        $leg_fare = 1;
        // TODO!
        $leg = [
            'id' => $leg_id,
            'arrival_time' => "1569311499",
            'arrival_time_zone' => $destination['timezone'],
            'arrival_timezone' => "Asia/Singapore",
            'departure_time' => "1569310392",
            'departure_time_zone' => $origin['timezone'],
            'departure_timezone' => "Asia/Singapore",
            'distance' => $oldTrip['distance'],
            'duration' => $oldTrip['duration'],
            'fare_raw' => 1,
            'polyline' => $overview_polyline,
            'quote' => 1,
            'steps' => count($leg_steps),
        ];
        $options = [
            'gid' => $leg_id, /* ??? */
            'leg_fare' => [$leg_id => $leg_fare],
            'leg_steps' => [$leg_id => $leg_steps],
            'legs' => [$leg],
            'routes' => 1
        ];
        $rideshare['options'] = $options;
        $newTrip['rideshare'] = $rideshare;
        if (count($trips)>2) {
            array_shift($trips); // Remove the first element
        }
        $trips[] = $newTrip;
        return $trips;
    }
}
