<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use Validator;
use App\Responses;
use App\Helper;
use App\Models\Dummy;

class DummyController extends Controller
{
	public function api_haversineGreatCircleDistance(Request $req)
	{
		try {
			$apiResp = Responses::success();
			$apiResp['data'] = [];
			
			// round up with precisions digits = 4
			
			// $distance == miles
			// $distance = Helper::haversineGreatCircleDistance($req->start_lat, $req->start_lng, $req->end_lat, $req->end_lng, Helper::EARTH_RADIUS_MILES);
			// $apiResp['data']['distance_in_km'] = round($distance*1.609, 4);
			// $apiResp['data']['distance_in_miles'] = round($distance, 4);
			// $apiResp['data']['distance_in_meters'] = round($distance*1609, 4);

			// $distance == km
			// $distance = Helper::haversineGreatCircleDistance($req->start_lat, $req->start_lng, $req->end_lat, $req->end_lng, Helper::EARTH_RADIUS_KM);
			// $apiResp['data']['distance_in_km'] = round($distance, 4);
			// $apiResp['data']['distance_in_miles'] = round($distance/1.609, 4);
			// $apiResp['data']['distance_in_meters'] = round($distance*1000, 4);

			// $distance == meters
			$distance = Helper::haversineGreatCircleDistance($req->start_lat, $req->start_lng, $req->end_lat, $req->end_lng, Helper::EARTH_RADIUS_M);
			$apiResp['data']['distance_in_km'] = round($distance / 1000, 4);
			$apiResp['data']['distance_in_miles'] = round($distance / 1609, 4);
			$apiResp['data']['distance_in_meters'] = round($distance, 4);

			return (new Response($apiResp, $apiResp['meta']['code']));
		} catch (\Exception $e) {
			$apiResp = Responses::error($e->getMessage());
			return (new Response($apiResp, $apiResp['meta']['code']));
		}
	}

	public function api_addBatchDummyTracks(Request $req)
	{
		try {
			$now = time();
			$apiResp = Responses::success();
			$batch_tracks = $req->batch_tracks;
			DB::beginTransaction();

			foreach ($batch_tracks as $key => $val) {
				$batch_tracks[$key]['crt'] = $now;
				$now = strtotime('+2 seconds', $now);
				Dummy::addDummyTrack($batch_tracks[$key]);
			}
			$apiResp['data'] = $batch_tracks;

			DB::commit();
			return (new Response($apiResp, $apiResp['meta']['code']));
		} catch (\Exception $e) {
			DB::rollBack();
			$apiResp = Responses::error($e->getMessage());
			return (new Response($apiResp, $apiResp['meta']['code']));
		}
	}

	public function api_getTracksBySeconds(Request $req)
	{
		try {
			$routes = Dummy::getByGpsId($req->gps_id);
			if (!isset($routes[0])) {
				$apiResp = Responses::not_found();
				return (new Response($apiResp, $apiResp['meta']['code']));
			}

			/**
			 * ngebandingin dari row yg belum berbeda ke row berikutnya
			 * jika data: 2,4,6,8,10
			 * diff_sec: 2
			 * results: 2,6,...
			 * diff_sec: 4
			 * results: 2,8,...
			 * diff_sec: 6
			 * results: 2,10,...
			 */
			// $start_now = strtotime('+'.$req->sec.' seconds', $routes[0]->crt);
			// $init_per_chunk = 0;
			// foreach ($routes as $key => $val) {
			// 	if ($init_per_chunk == 1) {
			// 		if ($val->crt >= $start_now) {
			// 			$start_now = strtotime('+'.$req->sec.' seconds', $routes[$key-1]->crt);
			// 			$init_per_chunk = 0;
			// 		}
			// 		continue;
			// 	}
			// 	$init_per_chunk = 1;
			// 	$chunk_by_sec[] = $val;
			// }

			/**
			 * ngebandingin dari row yg belum berbeda ke row berikutnya
			 * jika data: 2,4,6,8,10,12,14
			 * diff_sec: 2
			 * results: 2,4,6,8
			 * diff_sec: 4
			 * results: 2,6,10
			 * diff_sec: 6
			 * results: 2,8,14
			 */
			$chunk_by_sec = [];
			$chunk_by_sec[] = $routes[0];
			foreach ($routes as $key => $val) {
				$diffSec = $val->crt - end($chunk_by_sec)->crt;
				if ($diffSec >= $req->sec) {
					$chunk_by_sec[] = $val;
				}
			}

			$apiResp = Responses::success();
			$apiResp['total'] = count($chunk_by_sec);
			$apiResp['data'] = $chunk_by_sec;

			return (new Response($apiResp, $apiResp['meta']['code']));
		} catch (\Exception $e) {
			$apiResp = Responses::error($e->getMessage());
			return (new Response($apiResp, $apiResp['meta']['code']));
		}
	}

	public function api_addDummyHub(Request $req)
	{
		try {
			$now = time();
			DB::beginTransaction();

			$input = [
				'name' => $req->name,
				'lat' => $req->lat,
				'lng' => $req->lng,
				'polygon' => $req->polygon,
			];
			$rulesInput = [
				'name' => 'required|string|max:45',
				'lat' => 'required',
				'lng' => 'required',
				'polygon' => 'required|array',
				'polygon.*.lat' => 'required',
				'polygon.*.lng' => 'required',
			];

			// validasi input
			$isValidInput = Validator::make($input, $rulesInput);
			if (!$isValidInput->passes()) {
				$apiResp = Responses::bad_input($isValidInput->messages()->first());
				DB::rollBack();
				return new Response($apiResp, $apiResp['meta']['code']);
			}

			/**
			 * The axis order for coordinates in WKT is Cartesian, so (X Y) or (longitude latitude).
			 * https://stackoverflow.com/questions/29315117/what-is-the-correct-mysql-polygon-format-for-latitude-and-longitude
			 * https://stackoverflow.com/questions/5756232/moving-lat-lon-text-columns-into-a-point-type-column
			 */

			$ins = [
				'name' => $req->name,
				'lat' => $req->lat,
				'lng' => $req->lng,
				'lnglat' => DB::raw("ST_GeomFromText('POINT($req->lng $req->lat)')"),
				'shape' => "ST_GeomFromText('MULTIPOINT(",
			];
			foreach ($req->polygon as $key => $val) {
				$ins['shape'] .= $val['lng'] . " " . $val['lat'].", ";
			}
			$ins['shape'] = substr($ins['shape'], 0, -2);
			$ins['shape'] .= ")')";
			$ins['shape'] = DB::raw($ins['shape']);
			// return (new Response($ins['shape'], 200));
			Dummy::addDummyHub($ins);

			$apiResp = Responses::success();
			DB::commit();
			return (new Response($apiResp, $apiResp['meta']['code']));
		} catch (\Exception $e) {
			DB::rollBack();
			$apiResp = Responses::error($e->getMessage());
			return (new Response($apiResp, $apiResp['meta']['code']));
		}
	}

	public function api_nearestHub(Request $req)
	{
		try {
			$now = time();

			$input = [
				'lat' => $req->lat,
				'lng' => $req->lng,
			];
			$rulesInput = [
				'lat' => 'required',
				'lng' => 'required',
			];

			// validasi input
			$isValidInput = Validator::make($input, $rulesInput);
			if (!$isValidInput->passes()) {
				$apiResp = Responses::bad_input($isValidInput->messages()->first());
				return new Response($apiResp, $apiResp['meta']['code']);
			}

			$apiResp = Responses::success();
			/**
			 * The axis order for coordinates in WKT is Cartesian, so (X Y) or (longitude latitude).
			 * https://stackoverflow.com/questions/29315117/what-is-the-correct-mysql-polygon-format-for-latitude-and-longitude
			 * https://stackoverflow.com/questions/5756232/moving-lat-lon-text-columns-into-a-point-type-column
			 */

			$apiResp['data'] = Dummy::nearestHubInCircle($req->lat, $req->lng);

			return (new Response($apiResp, $apiResp['meta']['code']));
		} catch (\Exception $e) {
			$apiResp = Responses::error($e->getMessage());
			return (new Response($apiResp, $apiResp['meta']['code']));
		}
	}
}
