<?php

namespace apexl\Io\services;

use apexl\ClassEngine\EngineSingleton;
use apexl\Io\includes\System;
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 set the current path based on the request.
     */
    protected function setCurrentPath(): void
    {
        if (System::isCli()) {
            $this->currentPathData = [];

            return;
        }
        //account for windows weirdness
        $requestUri = $_SERVER['REQUEST_URI'];
        //if the first 2 chars are slashes, take one off.
        if (str_starts_with((string) $requestUri, "//")) {
            $requestUri = substr((string) $requestUri, 2);
        }
        $pathInfo = pathinfo((string) $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'],
        ];
    }

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

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

        return $routeContext->getRoute();
    }

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

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

    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));
    }

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

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

    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 $this->route !== null ? $this->route->setArgument($arg, $value) : false;
    }

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

        return $route->getArgument($arg, $default);
    }
}
