<?php
namespace apexl\Io\services;

use apexl\ClassEngine\EngineSingleton;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Routing\RouteContext;

class pathUtility extends EngineSingleton {

    protected $currentPathData;
    protected $route;

    protected function __construct()
    {
        parent::__construct();
        $this->setCurrentPath();
    }

    /**
     * Function to get either the full path, or a single element of it.
     * @param bool $position
     * @param bool $withQuery
     * @return string
     */
    public function getPath($position = FALSE, $withQuery = FALSE): string
    {
        if($position !== FALSE){
            return $this->currentPathData['path_items'][$position] ?? '';
        } elseif ($withQuery) {
            return $this->currentPathData['full_path'];
        } else {
            return $this->currentPathData['full_path_no_query'];
        }
    }

    public function getRouteName(Request $request){
        return $this->getRoute($request)->getName();
    }

    public function getRouteMethods(Request $request){
        return $this->getRoute($request)->getMethods();
    }

    public function getRouteArgs(Request $request){
        return $this->getRoute($request)->getArguments();
    }

    public function getNumElements(){
        return count($this->currentPathData['path_items']);
    }

    public function getLastItem(){
        //its a 0 indexed array so to get the last item simply take one off the total.
        return $this->getPath(($this->getNumElements() -1));
    }

    public function setCurrentRoute($route){
        $this->route = $route;
        return $this;
    }

    /**
     * @return mixed
     */
    public function getCurrentRouteName(){
        return $this->route->getName();
    }

    /**
     * @param $arg
     * @param $value
     * @return false
     */
    public function setCurrentRouteArgs($arg, $value){
        return isset($this->route) ? $this->route->setArgument($arg, $value) : FALSE;
    }

    /**
     * Function to set the current path based on the request.
     */
    protected function setCurrentPath(){
        //account for windows weirdness
        $requestUri = $_SERVER['REQUEST_URI'];
        //if the first 2 chars are slashes, take one off.
        if(substr($requestUri, 0, 2) == "//") {
            $requestUri = substr($requestUri, 2);
        }
        $pathInfo = pathinfo($requestUri);
        $fullPath = $pathInfo['dirname'] != DIRECTORY_SEPARATOR ? ltrim($pathInfo['dirname'].DIRECTORY_SEPARATOR.$pathInfo['basename'], DIRECTORY_SEPARATOR) : ltrim($pathInfo['dirname'].$pathInfo['basename'], DIRECTORY_SEPARATOR);
        $pathItems = $pathInfo['dirname'] != DIRECTORY_SEPARATOR ? explode(DIRECTORY_SEPARATOR, strtok($fullPath, '?')) : [strtok($fullPath, '?')];
        $this->currentPathData = [
            'full_path_no_query' => $fullPath != DIRECTORY_SEPARATOR ? implode(DIRECTORY_SEPARATOR, $pathItems) : $fullPath,
            'full_path' => $fullPath,
            'path_items' => $pathItems,
            'no_path_items' => count($pathItems),
            'endpoint' => $pathInfo['basename']
        ];
    }

    /**
     * @param Request $request
     * @return \Slim\Interfaces\RouteInterface|null
     */
    protected function getRoute(Request $request){
        $routeContext = RouteContext::fromRequest($request);
        return $routeContext->getRoute();
    }

    public function getRouteArg(Request $request, $arg, $default = ''){
        $route = $this->getRoute($request);
        return $route->getArgument($arg, $default);
    }
}