<?php

namespace App\Services\GoogleMaps\Request;

use ErrorException;

/**
 * Class GoogleGeoCoder
 *
 * @package App\Packages\GoogleMaps
 */
class GoogleGeoCoderQuery
{
	const STATUS_OK = 'OK';
	const STATUS_ZERO_RESULTS = 'ZERO_RESULTS';
	const STATUS_OVER_DAILY_LIMIT = 'OVER_DAILY_LIMIT';
	const STATUS_OVER_QUERY_LIMIT = 'OVER_QUERY_LIMIT';
	const STATUS_REQUEST_DENIED = 'REQUEST_DENIED';
	const STATUS_INVALID_REQUEST = 'INVALID_REQUEST';
	const STATUS_UNKNOWN_ERROR = 'UNKNOWN_ERROR';

	const MAPS_URL = 'https://maps.googleapis.com/maps/api/geocode/json';
	const PLACES_URL = 'https://maps.googleapis.com/maps/api/place/autocomplete/json';
	const PLACES_LAT_LNG_URL = 'https://maps.googleapis.com/maps/api/place/nearbysearch/json';
	const PLACE_DETAILS_URL = 'https://maps.googleapis.com/maps/api/place/details/json';

	protected $key;
	protected $radius;

	public function __construct()
	{
		$this->key = env('GOOGLE_MAPS_API_KEY');
		$this->radius = env('GOOGLE_MAPS_RADIUS', 150);
	}

	/**
	 * @param $address
	 *
	 * @return array
	 */
	public function requestExactAddress($address)
	{
		$queryParams = http_build_query([
			'key' => $this->key,
			'address' => $address
		]);

		return $this->makeApiRequest(self::MAPS_URL . '?' . $queryParams);
	}

    /**
     * @param string $address
     * @param string $sessionId
     * @param string $locale
     * @param string|null $lat
     * @param string|null $lng
     *
     * @return array
     */
	public function requestPlaceList($address, $sessionId, $locale, $lat = null, $lng = null)
	{
		$query = [
			'key' => $this->key,
			'input' => $address,
			'language' => $locale,
			'session_token' => $sessionId,
		];

		if ($lat && $lng) {
		    $query['location'] = $lat . ", " . $lng;
		    $query['radius'] = $this->radius;
        }

		$queryParams = http_build_query($query);

		return $this->makeApiRequest(self::PLACES_URL . '?' . $queryParams);
	}

	/**
	 * @param $lat
	 * @param $lng
	 * @param $sessionId
	 * @param $locale
	 *
	 * @return array
	 */
	public function requestPlaceListLatLng($lat, $lng, $sessionId, $locale)
	{
		$queryParams = http_build_query([
			'key' => $this->key,
			'location' => $lat . ", " . $lng,
			'language' => $locale,
			'session_token' => $sessionId,
            'rankby' => 'distance',
		]);

		return $this->makeApiRequest(self::PLACES_LAT_LNG_URL . '?' . $queryParams);
	}

    /**
     * @param string $googleMapsPlaceId
     * @param string $sessionId
     * @param string $locale
     *
     * @return array
     */
    public function requestPlaceDetails($googleMapsPlaceId, $sessionId, $locale)
    {
        $queryParams = http_build_query([
            'key' => $this->key,
            'place_id' => $googleMapsPlaceId,
            'language' => $locale,
            'session_token' => $sessionId,
        ]);

        return $this->makeApiRequest(self::PLACE_DETAILS_URL . '?' . $queryParams);
    }

	/**
	 * @param $requestUrl
	 *
	 * @return array
	 */
	protected function makeApiRequest($requestUrl)
	{
		try {
			$response = file_get_contents($requestUrl);

		} catch (ErrorException $errorException) {
			return ['status' => self::STATUS_UNKNOWN_ERROR];
		}

		return json_decode($response, true);
	}
}
