<?php

namespace Lc\SovBundle\Component;

use Geocoder\Model\Coordinates;
use Geocoder\Provider\Addok\Addok;
use Geocoder\Provider\GoogleMaps\GoogleMaps;
use Geocoder\Provider\Nominatim\Nominatim;
use Geocoder\Query\GeocodeQuery;
use Geocoder\Query\ReverseQuery;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpClient\HttplugClient;

class CitiesComponent
{
    protected ParameterBagInterface $parameterBag;

    public function __construct(ParameterBagInterface $parameterBag)
    {
        $this->parameterBag = $parameterBag;
    }

    public function callCitiesApi($method, $url, $data = false)
    {
        $url = 'https://geo.api.gouv.fr/' . $url;
        $curl = curl_init();

        switch ($method) {
            case "POST":
                curl_setopt($curl, CURLOPT_POST, 1);

                if ($data) {
                    curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
                }
                break;
            case "PUT":
                curl_setopt($curl, CURLOPT_PUT, 1);
                break;
            default:
                if ($data) {
                    $url = sprintf("%s?%s", $url, http_build_query($data));
                }
        }

        // Optional Authentication:
        curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
        curl_setopt($curl, CURLOPT_USERPWD, "username:password");

        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

        $result = curl_exec($curl);

        curl_close($curl);

        return $result;
    }

    public function getGeocoderProvider()
    {
        $provider = false;
        $symfonyClient = new HttplugClient();
        $configGeocoderProvider = $this->parameterBag->get('geocoder.provider');

        /* API du gouvernement */
        if ($configGeocoderProvider == 'addok') {
            $provider = new Addok($symfonyClient, 'https://api-adresse.data.gouv.fr');
        } /* Google Maps */
        elseif ($configGeocoderProvider == 'googlemaps') {
            $provider = new GoogleMaps($symfonyClient, null, $this->parameterBag->get('geocoder.api_key'));
        } /* Nominatim : OpenStreetMap */
        elseif ($configGeocoderProvider == 'nominatim') {
            $provider = Nominatim::withOpenStreetMapServer(
                    $symfonyClient,
                    'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion'
            );
        }

        if (!$provider) {
            throw new \ErrorException('Aucun provider (geocoding) défini');
        }

        return $provider;
    }

    public function callAddressApi($query)
    {
        $resultsToReturn = [];

        if(!is_null($query)) {
            $provider = $this->getGeocoderProvider() ;
            $query = GeocodeQuery::create($query)->withData('type', 'housenumber');
            $results = $provider->geocodeQuery($query);

            foreach($results as $result) {
                if ($result->getStreetNumber() && strlen($result->getStreetNumber()) > 0) {
                    $resultsToReturn[] = $result;
                }
            }
        }

        return $resultsToReturn;
    }

    public function callReverseAddressApi($latitude, $longitude)
    {
        $provider = $this->getGeocoderProvider() ;;
        $query = ReverseQuery::create(new Coordinates($latitude, $longitude));
        $results = $provider->reverseQuery($query);
        return $results->all() ;
    }

    public function getZipByCity($city, $code = null)
    {
        $zip = null;

        $paramsSearch = [
                'nom' => $city,
                'fields' => 'nom,codesPostaux'
        ];

        if ($code != null && $code != 0) {
            $paramsSearch['code'] = $code;
        }

        $returnCitiesSearchZip = json_decode($this->callCitiesApi('get', 'communes', $paramsSearch));

        if ($returnCitiesSearchZip) {
            foreach ($returnCitiesSearchZip as $citySearchZip) {
                if (strtolower(trim($city)) == strtolower(trim($citySearchZip->nom))) {
                    $zip = $citySearchZip->codesPostaux[0];
                }
            }
        }

        return $zip;
    }

}