<?php
namespace App\Services\Generators;
use Illuminate\Support\Facades\Storage;
use App\Models\Quote;

class ImgGenerator {
	public static function generate(Quote $quote, bool $wider = false, bool $force = false): array {
		$path = "quotes/{$quote->id}/img-" . ($wider ? '01' : '02') . ".jpg";
		if(!$force && Storage::exists($path)) return [0, Storage::get($path)];
		$url = self::imgurl($quote, $wider);
		$x = file_get_contents($url);
		if($x !== FALSE) {
			ob_start();
			imagejpeg(imagecreatefromstring($x), NULL, 50);
			$x = ob_get_clean();
			}
		Storage::put($path, $x);
		return [1, $x];
		}
	private static function imgurl($quote, $wider = 0) {
		$base = 'https://maps.googleapis.com/maps/api/staticmap';

		$params = [
			'size'    => '320x320',
			'scale'   => 4,
			'maptype' => 'satellite',
			'key'     => config('services.google.maps.server'),
			'path' => sprintf(
				'color:0xFFFF00FF|weight:4|enc:%s',
				self::polyline($quote)
				),
			'visible' => self::bounds($quote, $wider),
			];
		return $base . '?' . http_build_query($params, '', '&', PHP_QUERY_RFC3986);
		}
	private static function bounds($quote, $wider) {
		$wratio = 1.2;
		$wmod = 0.001;
		$x = $quote->coords;
		$lts = array_column($x, 0);
		$lgs = array_column($x, 1);
		$ltmin = min($lts);
		$ltmax = max($lts);
		$lgmin = min($lgs);
		$lgmax = max($lgs);
		if($wider) {
			$ltdif = $ltmax - $ltmin;
			$ltdif = $ltdif * $wratio;
			$lgdif = $lgmax - $lgmin;
			$lgdif = $lgdif * $wratio;
			$ltmin = $ltmin - $ltdif - $wmod;
			$ltmax = $ltmax + $ltdif + $wmod;
			$lgmin = $lgmin - $lgdif - $wmod;
			$lgmax = $lgmax + $lgdif + $wmod;
			}
		return "$ltmin,$lgmin|$ltmin,$lgmax|$ltmax,$lgmin|$ltmax,$lgmax";
		}
	private static function polyline($quote) {
		$x = $quote->coords;
		$z = array_shift($x);
		$x[] = $z;
		$p = self::polypoint($z[0]) . self::polypoint($z[1]);
		foreach($x as $y) {
			$p .= self::polypoint($y[0] - $z[0]) . self::polypoint($y[1] - $z[1]);
			$z = $y;
			}
		return $p;
		}
	private static function polypoint($x) {
		$z = ($x < 0);
		$x = round($x * 100000);
		$x = $x << 1;
		if($z) $x =~ $x;
		$x = decbin($x);
		$y = str_split($x);
		$x = [];
		$p = '';
		for($c = count($y) - 1;
		$c >= 0; $c--) {
			$p = $y[$c] . $p;
			if(strlen($p) == 5) {
				$x[] = $p;
				$p = '';
				}
			}
		if(strlen($p) > 0) $x[] = str_pad($p, 5, 0, STR_PAD_LEFT);
		for($c = 0; $c < count($x); $c++) {
			if($c != count($x) - 1) $x[$c] = chr(bindec($x[$c]) + 95);
			else $x[$c] = chr(bindec($x[$c]) + 63);
			}
		return implode('', $x);
		}
	}
