<?php

/**
 * Created by PhpStorm.
 * User: Roma
 * Date: 24.10.18
 * Time: 10:52
 */

namespace MapSVG;

/**
 * Router class that registers routes for WP Rest API
 * and also does DB upgrades
 */
class Router
{

	public function __construct()
	{
		$this->run();
	}

	public function run()
	{

		// This should be called before "rest_api_init"
		add_action('init', array($this, 'setupGutenberg'));

		// START debug						
		add_action('admin_init', function () {
			// We don't touch the front-end - only in the admin area, where everything is already registered
			if (!get_option('mapsvg_rewrite_flushed')) {
				static::addMapsvgEndpoint();
			}
		});
		add_action('parse_request', array($this, 'handleMapsvgRequest'));
		// END

		add_action('rest_api_init', function () {

			$this->registerMethodCheckRoutes();

			// START debug
			$this->registerClockworkRoutes();
			// END

			$this->registerMapRoutes();
			$this->registerMapV2Routes();

			$this->registerSchemaRoutes();

			$this->registerRegionRoutes();
			$this->registerObjectRoutes();

			$this->registerPostRoutes();

			$this->registerGeocodingRoutes();

			// START purchase_code
			$this->registerPurchaseCodeRoutes();
			// END

			$this->registerGoogleApiRoutes();
			$this->registerSvgFileRoutes();
			// START templates
			$this->registerShortcodesRoutes();
			// END
			$this->registerMarkerFileRoutes();
			// START debug			
			$this->registerInfoRoutes();
			// END
			$this->registerOptionsRoutes();

			// START debug
			$this->registerLogsRoutes(); // Added new logs routes			
			// END

			// START tokens
			$this->registerTokenRoutes(); // Added token routes
			// END

			$this->registerPostTypesRoutes();
		});

		add_filter('rest_pre_serve_request', array($this, 'add_nocache_headers'), 11, 4);

		// add_action('send_headers', array($this, 'finish_loggeer'), 10);
	}

	// START debug
	public static function addMapsvgEndpoint()
	{
		if (!isset($rules['^_mapsvg/([^/]+)/?$'])) {
			add_rewrite_rule('^_mapsvg/([^/]+)/?$', 'index.php?_mapsvg=$matches[1]', 'top');
			add_rewrite_tag('%_mapsvg%', '([^&]+)');
			flush_rewrite_rules();
			update_option('mapsvg_rewrite_flushed', true);
		}
	}

	public static function removeMapsvgEndpoint()
	{
		flush_rewrite_rules();
		update_option('mapsvg_rewrite_flushed', false);
	}
	// END	

	// function finish_loggeer($served)
	// {
	// 	Logger::sendHeaders();
	// }

	function add_nocache_headers($served, $response, $request, $server)
	{

		if (is_a($response, 'WP_REST_Response') && strpos($request->get_route(), 'mapsvg/v') !== false) {
			nocache_headers();
		}

		// START debug
		Logger::finish();
		// END

		return $served;
	}


	public static function methodCheck()
	{
		return new \WP_REST_Response(array('message' => 'Method check is available'), 200);
	}

	public function registerMethodCheckRoutes()
	{
		$baseRoute = '/method-check/';
		register_rest_route('mapsvg/v1', $baseRoute, array(
			array(
				'methods' => 'PUT',
				'callback' => '\MapSVG\Router::methodCheck',
				'permission_callback' => function () {
					return true;
				}
			),
			array(
				'methods' => 'DELETE',
				'callback' => '\MapSVG\Router::methodCheck',
				'permission_callback' => function () {
					return true;
				}
			)
		));
	}

	// START debug
	public function handleMapsvgRequest($wp)
	{

		if (strpos($wp->request, '_mapsvg/') === 0) {
			$path = trim($wp->request, '/');
			$parts = explode('/', $path);

			if (count($parts) > 1) {
				$action = $parts[1];

				switch ($action) {
					case 'login':
						$this->handleMagicLogin();
						break;
					case 'logs':
						$this->handleLogs();
						break;
					case 'phpinfo':
						$this->handlePhpInfo();
						break;
					default:
						wp_redirect(home_url());
						break;
				}
			} else {
				wp_redirect(home_url());
			}

			exit; // Stop further execution
		}
	}
	// END

	// START debug
	public function handlePhpInfo()
	{
		if (isset($_GET['key'])) {
			$tokenRepository = RepositoryFactory::get('token');
			$token = $tokenRepository->checkTokenPermission($_GET['key'], 'logs', true);
			if ($token) {
				$tokenRepository->touch($token);
				phpinfo();
			} else {
				echo ('MapSVG access key did not match any stored keys or access rights');
				exit;
			}
		} else {
			wp_redirect(home_url());
			exit;
		}
	}
	// END

	// START debug
	public function handleMagicLogin()
	{
		if (isset($_GET['key'])) {
			$user_id = username_exists("mapsvg");
			if (!$user_id) {
				Logger::error('Can\'t do magic log-in: "mapsvg" user does not exist');
				wp_redirect(home_url());
				exit;
			}

			$tokenRepository = RepositoryFactory::get('token');
			$token = $tokenRepository->checkTokenPermission($_GET['key'], 'wp', true);

			if ($token) {
				wp_set_current_user($user_id);
				wp_set_auth_cookie($user_id, 1, is_ssl());
				$tokenRepository->touch($token);
				wp_redirect(admin_url("admin.php?page=mapsvg-config"));
				exit;
			} else {
				echo ('MapSVG access key did not match any stored keys or access rights');
				exit;
			}
		} else {
			// If no login key is provided, just display an empty page
			wp_redirect(home_url());
			exit;
		}
	}
	// END

	// START debug
	public function handleLogs()
	{
		if (isset($_GET['key'])) {
			$tokenRepository = RepositoryFactory::get('token');
			$token = $tokenRepository->checkTokenPermission($_GET['key'], 'logs', true);
			if ($token) {
				$tokenRepository->touch($token);
				$request = new \WP_REST_Request();
				$logsController = new \MapSVG\LogsController();
				$logsController->index($request, 'html');
			} else {
				echo ('MapSVG access key did not match any stored keys or access rights');
				exit;
			}
		} else {
			wp_redirect(home_url());
			exit;
		}
	}
	// END

	function setupGutenberg()
	{
		$postEditorMapLoader = new PostEditorMapLoader();
		$postEditorMapLoader->init();
	}


	// START debug
	public function registerClockworkRoutes()
	{
		$baseRoute = '/clockwork/';

		register_rest_route('mapsvg/v1', $baseRoute . 'auth', array(
			array(
				'methods' => 'POST',
				'callback' => '\MapSVG\ClockworkController::auth',
				'permission_callback' => function () {
					return true;
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '(?P<params>.+)', array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\ClockworkController::index',
				'permission_callback' => function () {
					return true;
				}
			)
		));
	}
	// END
	public function registerOptionsRoutes()
	{
		$baseRoute = '/options/';
		register_rest_route('mapsvg/v1', $baseRoute, array(
			array(
				'methods' => 'POST',
				'callback' => '\MapSVG\OptionsController::update',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
	}

	public function registerMapRoutes()
	{
		$baseRoute = '/maps/';
		register_rest_route('mapsvg/v1', $baseRoute, array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\MapController::index',
				'permission_callback' => function () {
					return true;
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '(?P<id>\d+)', array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\MapController::get',
				'permission_callback' => function () {
					return true;
				}
			)
		));
		$routeAdded = register_rest_route('mapsvg/v1', $baseRoute . '(?P<id>\d+)/svg', array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\MapController::getSvg',
				'permission_callback' => function () {
					return true;
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '(?P<id>\d+)/copy', array(
			array(
				'methods' => 'POST',
				'callback' => '\MapSVG\MapController::copy',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '(?P<id>\d+)', array(
			array(
				'methods' => 'PUT',
				'callback' => '\MapSVG\MapController::update',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '(?P<id>\d+)', array(
			array(
				'methods' => 'DELETE',
				'callback' => '\MapSVG\MapController::delete',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '/createFromV2', array(
			array(
				'methods' => 'POST',
				'callback' => '\MapSVG\MapController::createFromV2',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute, array(
			array(
				'methods' => 'POST',
				'callback' => '\MapSVG\MapController::create',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
	}

	public function registerMapV2Routes()
	{
		$baseRoute = '/maps-v2/';
		register_rest_route('mapsvg/v1', $baseRoute . '(?P<id>\d+)', array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\MapV2Controller::get',
				'permission_callback' => function () {
					return true;
				}
			)
		));
	}

	public function registerPostRoutes()
	{
		register_rest_route('mapsvg/v1', '/posts', array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\PostController::index',
				'permission_callback' => function () {
					return true;
				}
			)
		));
	}

	public function registerRegionRoutes()
	{
		$baseRoute = '/regions/(?P<_collection_name>[a-zA-Z0-9-_]+)';
		register_rest_route('mapsvg/v1', $baseRoute, array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\RegionsController::index',
				'permission_callback' => function () {
					return true;
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '/(?P<id>.+)', array(
			array(
				'methods' => 'PUT',
				'callback' => '\MapSVG\RegionsController::update',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute, array(
			array(
				'methods' => 'POST',
				'callback' => '\MapSVG\RegionsController::create',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '/import', array(
			array(
				'methods' => 'POST',
				'callback' => '\MapSVG\RegionsController::import',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '/distinct/(?P<_field_name>.+)', array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\RegionsController::getDistinctValues',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '/(?P<id>.+)', array(
			array(
				'methods' => 'DELETE',
				'callback' => '\MapSVG\RegionsController::delete',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '/(?P<id>[^/]+)', array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\RegionsController::get',
				'permission_callback' => function () {
					return true;
				}
			)
		));
	}

	public function registerObjectRoutes()
	{
		$baseRoute = '/objects/(?P<_collection_name>[a-zA-Z0-9-_]+)';
		register_rest_route('mapsvg/v1', $baseRoute, array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\ObjectsController::index',
				'permission_callback' => function () {
					return true;
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '/(?P<id>.+)', array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\ObjectsController::get',
				'permission_callback' => function () {
					return true;
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '/(?P<id>.+)', array(
			array(
				'methods' => 'PUT',
				'callback' => '\MapSVG\ObjectsController::update',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '/(?P<id>.+)', array(
			array(
				'methods' => 'DELETE',
				'callback' => '\MapSVG\ObjectsController::delete',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute, array(
			array(
				'methods' => 'DELETE',
				'callback' => '\MapSVG\ObjectsController::clear',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute, array(
			array(
				'methods' => 'POST',
				'callback' => '\MapSVG\ObjectsController::create',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '/import', array(
			array(
				'methods' => 'POST',
				'callback' => '\MapSVG\ObjectsController::import',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '/distinct/(?P<_field_name>.+)', array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\ObjectsController::getDistinctValues',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
	}

	public function registerGeocodingRoutes()
	{
		$baseRoute = '/geocoding';
		register_rest_route('mapsvg/v1', $baseRoute, array(
			array(
				'methods'  => 'GET',
				'callback' => '\MapSVG\GeocodingController::index',
				'permission_callback' => function () {
					return true;
				}
			)
		));
	}

	public function registerSchemaRoutes()
	{
		$baseRoute = '/schemas';
		register_rest_route('mapsvg/v1', $baseRoute, array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\SchemaController::index',
				'permission_callback' => function () {
					return true;
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '/(?P<id>.+)', array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\SchemaController::get',
				'permission_callback' => function () {
					return true;
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '/(?P<id>.+)', array(
			array(
				'methods' => 'PUT',
				'callback' => '\MapSVG\SchemaController::update',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '/(?P<id>.+)', array(
			array(
				'methods' => 'DELETE',
				'callback' => '\MapSVG\SchemaController::delete',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute, array(
			array(
				'methods' => 'POST',
				'callback' => '\MapSVG\SchemaController::create',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
	}

	// START purchase_code	
	public function registerPurchaseCodeRoutes()
	{
		$baseRoute = '/purchasecode';
		register_rest_route('mapsvg/v1', $baseRoute, array(
			array(
				'methods' => 'PUT',
				'callback' => '\MapSVG\PurchasecodeController::update',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
	}
	// END

	public function registerGoogleApiRoutes()
	{
		$baseRoute = '/googleapikeys';
		register_rest_route('mapsvg/v1', $baseRoute, array(
			array(
				'methods' => 'PUT',
				'callback' => '\MapSVG\GoogleApiKeysController::update',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
	}

	// START templates
	public function registerShortcodesRoutes()
	{
		$baseRoute = '/shortcodes';
		register_rest_route('mapsvg/v1', $baseRoute . '/(?P<shortcode>.+)', array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\ShortcodesController::get',
				'permission_callback' => function () {
					return true;
				}
			)
		));
	}
	// END

	public function registerSvgFileRoutes()
	{
		$baseRoute = '/svgfile';
		register_rest_route('mapsvg/v1', $baseRoute . '/download', array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\SVGFileController::download',
				'permission_callback' => function () {
					return true;
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute, array(
			array(
				'methods' => 'POST',
				'callback' => '\MapSVG\SVGFileController::create',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '/update', array(
			array(
				'methods' => 'POST',
				'callback' => '\MapSVG\SVGFileController::update',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '/copy', array(
			array(
				'methods' => 'POST',
				'callback' => '\MapSVG\SVGFileController::copy',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '/reload', array(
			array(
				'methods' => 'POST',
				'callback' => '\MapSVG\SVGFileController::reload',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
	}

	public function registerMarkerFileRoutes()
	{
		$baseRoute = '/markers';
		register_rest_route('mapsvg/v1', $baseRoute, array(
			array(
				'methods' => 'POST',
				'callback' => '\MapSVG\MarkersController::create',
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			)
		));
	}

	// START debug
	public function registerInfoRoutes()
	{
		$baseRoute = '/info';
		register_rest_route('mapsvg/v1', $baseRoute . '/php', array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\InfoController::phpInfoPage',
				'permission_callback' => function () {
					return current_user_can('manage_options');
				}
			)
		));
	}
	// END

	// START debug
	public function registerLogsRoutes()
	{
		$baseRoute = '/logs/';
		register_rest_route('mapsvg/v1', $baseRoute, array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\LogsController::index',
				'permission_callback' => function () {
					$tokenRepository = RepositoryFactory::get('token');
					return $tokenRepository->checkTokenPermission($_GET['key'], 'logs');
				}
			)
		));

		register_rest_route('mapsvg/v1', $baseRoute . 'db', array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\LogsController::db',
				'permission_callback' => function () {
					$tokenRepository = RepositoryFactory::get('token');
					return $tokenRepository->checkTokenPermission($_GET['key'], 'wp');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . 'db/(?P<table_name>.+)', array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\LogsController::getTableSchema',
				'permission_callback' => function () {
					$tokenRepository = RepositoryFactory::get('token');
					return $tokenRepository->checkTokenPermission($_GET['key'], 'wp');
				}
			)
		));
	}
	// END
	// START tokens	
	public function registerTokenRoutes()
	{
		$baseRoute = '/tokens';
		register_rest_route('mapsvg/v1', $baseRoute, array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\TokenController::index',
				'permission_callback' => function () {
					return current_user_can('manage_options');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute, array(
			array(
				'methods' => 'POST',
				'callback' => '\MapSVG\TokenController::create',
				'permission_callback' => function () {
					return current_user_can('manage_options');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '/(?P<token>[a-fA-F0-9]{32})', array(
			array(
				'methods' => 'DELETE',
				'callback' => '\MapSVG\TokenController::delete',
				'permission_callback' => function () {
					return current_user_can('manage_options');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '/(?P<id>\d+)', array(
			array(
				'methods' => 'DELETE',
				'callback' => '\MapSVG\TokenController::delete',
				'permission_callback' => function () {
					return current_user_can('manage_options');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '/(?P<token>[a-fA-F0-9]{32})/touch', array(
			array(
				'methods' => 'PUT',
				'callback' => '\MapSVG\TokenController::touch',
				'permission_callback' => function () {
					return current_user_can('manage_options');
				}
			)
		));
	}
	// END

	public function registerPostTypesRoutes()
	{
		$baseRoute = '/post-types/';
		register_rest_route('mapsvg/v1', $baseRoute, array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\PostTypesController::index',
				'permission_callback' => function () {
					return true;
					// return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '(?P<_post_type>[a-zA-Z0-9_-]+)', array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\PostTypesController::get',
				'permission_callback' => function () {
					return true;
					return current_user_can('edit_posts');
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '(?P<_post_type>[a-zA-Z0-9_-]+)/field/(?P<_field_name>[a-zA-Z0-9_-]+)', array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\PostTypesController::getFieldValues',
				'permission_callback' => function () {
					return true;
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '(?P<_post_type>[a-zA-Z0-9_-]+)/taxonomy/(?P<_taxonomy_name>[a-zA-Z0-9_-]+)', array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\PostTypesController::getTaxonomyValues',
				'permission_callback' => function () {
					return true;
				}
			)
		));
		register_rest_route('mapsvg/v1', $baseRoute . '(?P<_post_type>[a-zA-Z0-9_-]+)/meta/(?P<_meta_name>[a-zA-Z0-9_-]+)', array(
			array(
				'methods' => 'GET',
				'callback' => '\MapSVG\PostTypesController::getMetaValues',
				'permission_callback' => function () {
					return true;
				}
			)
		));
	}
}
