<?php

namespace Limesharp\Stockists\Model;

use Magento\Framework\Model\AbstractModel;
use Magento\Framework\Model\Context;
use Magento\Framework\Registry;
use Limesharp\Stockists\Block\Stockists;
use Magento\Framework\Model\ResourceModel\AbstractResource;
use Magento\Framework\Data\Collection\AbstractDb;

class Geocode extends AbstractModel
{

    private $stockistsBlock;

    public function __construct(
        Context $context,
        Registry $registry,
        Stockists $stockistsBlock,
        AbstractResource $resource = null,
        AbstractDb $resourceCollection = null,
        array $data = []
    ) {
        $this->stockistsBlock = $stockistsBlock;
        parent::__construct($context, $registry, $resource, $resourceCollection, $data);
    }

    //TODO: Check integrity and use to check geocoding results
//    private $_statusCode = array(
//        "OK", "ZERO_RESULTS", "OVER_QUERY_LIMIT", "REQUEST_DENIED", "INVALID_REQUEST", "UNKNOWN_ERROR"
//    );
//    private $_locationType = array(
//        "ROOFTOP",              //result is a precise geocode
//        "RANGE_INTERPOLATED",   //reflects an approximation (usually on a road) interpolated between two precise points (such as intersections). Interpolated results are generally returned when rooftop geocodes are unavailable for a street address.
//        "GEOMETRIC_CENTER",     //is the geometric center of a result such as a polyline (for example, a street) or polygon (region)
//        "APPROXIMATE"           //is approximate
//    );

    public function geocode($address) {
        if(empty($address)) {
            throw new \Exception('Empty address');
        }

        try {
            $geocoder = new \GoogleMapsGeocoder($address);
            $geocoder->setApiKey($this->stockistsBlock->getApiKeySettings());
            $response = $geocoder->geocode();

            if($response['status'] != "OK") {
                $errorMessage = $response['status'];
                if(!empty($response['error_message'])) {
                    $errorMessage .= ' - ' . $response['error_message'];
                }
                //TODO: Logging
                throw new \Exception($errorMessage);
            }

            $geocodeResponse['latitude'] = $response['results'][0]['geometry']['location']['lat'];
            $geocodeResponse['longitude'] = $response['results'][0]['geometry']['location']['lng'];

            //TODO: Logging
//            $response['status'];
//            $response['results'][0]['partial_match'];
//            $response['results'][0]['geometry']['location_type'];
//            $response['results'][0]['formatted_address'];

            return $geocodeResponse;
        } catch (\Exception $ex) {
            throw new \Exception($ex->getMessage());
        }
    }

    public function completeGeocode($address) {
        if(empty($address)) {
            throw new \Exception('Empty address');
        }

        try {
            $geocoder = new \GoogleMapsGeocoder($address);
            $geocoder->setApiKey($this->stockistsBlock->getApiKeySettings());
            $response = $geocoder->geocode();

            if($response['status'] != "OK") {
                $errorMessage = $response['status'];
                if(!empty($response['error_message'])) {
                    $errorMessage .= ' - ' . $response['error_message'];
                }
                //TODO: Logging
                throw new \Exception($errorMessage);
            }

            if(isset($response['results'][0]['partial_match']) && ($response['results'][0]['partial_match'] == 1)) {
                throw new \Exception('A partial match can not be taken for real');
            }

            foreach($response['results'][0]['address_components'] as $address) {
                $geocodeResponse[$address['types'][0]] = $address['short_name'];
            }

            if(empty($geocodeResponse['route']) || empty($geocodeResponse['locality']) || empty($geocodeResponse['country']) || empty($geocodeResponse['postal_code']) || empty($geocodeResponse['administrative_area_level_2'])) {
                throw new \Exception('Not enough information returned from Google Maps');
            }
            if(strlen($geocodeResponse['administrative_area_level_2']) != 2) {
                throw new \Exception('administrative_area_level_2 short_name ' . $geocodeResponse['administrative_area_level_2'] . ' has more than 2 character');
            }

            $geocodeResponse['latitude'] = $response['results'][0]['geometry']['location']['lat'];
            $geocodeResponse['longitude'] = $response['results'][0]['geometry']['location']['lng'];
            $geocodeResponse['formatted_address'] = $response['results'][0]['formatted_address'];

            return $geocodeResponse;
        } catch (\Exception $ex) {
            throw new \Exception($ex->getMessage());
        }
    }
}
