<?php

namespace Hura8\System\Controller;

use Hura8\Interfaces\AppResponse;
use Hura8\System\IDGenerator;
use Hura8\System\Language;
use Hura8\System\Model\UrlModel;
use Hura8\System\Url;
use Hura8\Traits\ClassCacheTrait;


class UrlManagerController
{

    use ClassCacheTrait;

    /* @var UrlModel $objUrlModel */
    protected  $objUrlModel;

    public function __construct() {
        $this->objUrlModel = new UrlModel();
    }


    public function createRedirect($info) {
        $request_path = $info['request_path'] ?? '';
        $redirect_code = $info['redirect_code'] ?? 0;
        $redirect_url = $info['redirect_url'] ?? '';

        if(!$request_path || !$redirect_url) {
            return false;
        }

        $request_path_element = Url::parse($request_path);

        $request_path_path = $request_path_element['path'];

        // home page or itself is forbidden
        if($request_path_path == '/' || $request_path_path == $redirect_url) {
            return false;
        }


        return $this->objUrlModel->create([
            "url_type" => "redirect",
            "request_path" => $request_path_path,
            "redirect_code" => $redirect_code,
            "redirect_url" => $redirect_url,
        ]);
    }


    public function getInfo($id) : ?array {
        return $this->objUrlModel->getInfo($id);
    }


    public function getEmptyInfo($addition_field_value = []) : array {
        return $this->objUrlModel->getEmptyInfo($addition_field_value);
    }


    public function getList(array $condition) : array
    {
        return $this->objUrlModel->getList($condition);
    }


    public function getTotal(array $condition) : int
    {
        return $this->objUrlModel->getTotal($condition);
    }


    public function deleteByRequestPath($request_path) {
        $this->objUrlModel->deleteByRequestPath($request_path);
    }


    public static function translateRequestPathConfig(
        $request_path_config, // "/%extra_path%/%item_index%/ac%item_id%.html",/
        $item_id = '',
        $item_index = '',
        $extra_path = ''
    ) {

        $item_index = static::create_url_index($item_index); //reclean url index

        $new_url = str_replace(
            array('%item_id%', '%item_index%', '%extra_path%',),
            array($item_id, $item_index, $extra_path),
            $request_path_config
        );

        return str_replace("//","/",$new_url);
    }


    public static function create_url_index($name, $vietnamese=true){
        if($vietnamese) $name = Language::chuyenKhongdau($name);

        $name = preg_replace("/[^a-z0-9\s_\-]/i", " ", $name);
        $name = preg_replace("/\s+/i", " ", $name);
        $name = str_replace(" ","-", trim($name));
        $name = preg_replace("/-+/","-", $name);

        if (!defined("BUILD_URL_INDEX_LOWERCASE") || BUILD_URL_INDEX_LOWERCASE) {
            return strtolower($name);
        }

        return $name;
    }


    public function getUrlMetaInfo($request_path){
        return $this->objUrlModel->getUrlMetaInfo($request_path);
    }


    public function createUrlMeta(array $info){
        return $this->objUrlModel->createUrlMeta($info);
    }


    public function getUrlInfoByRequestPath($request_path) {
        $info = $this->objUrlModel->getUrlByRequestPath($request_path);
        if($info){

            $id_path_content = $this->analyze_url_id_path($info['id_path']);

            $id_path_content['option']          = $id_path_content['module'];
            //$id_path_content['redirect_code']   = $info['redirect_code'];
            //$id_path_content['request_path']    = $info['request_path'];

            return array_merge($info, $id_path_content);
        }

        return false;
    }

    ///module:product/view:category/view_id:1/brand_id:55/type:hello-ther
    //return:
    /*
      [
        "module" => "product",
        "view" => "category",
        "view_id" => "1",
        'query' => [
            "brand_id" => 55,
            "type" => "hello-ther",
        ],
    ],
     * */
    protected function analyze_url_id_path($id_path) : array
    {
        $id_path_ele = explode("/", $id_path);

        $result = array();
        $query_string = array();

        foreach ( $id_path_ele as $ele ) {
            if(!$ele) continue;

            $ele_part =	explode(":", $ele);
            if(!in_array($ele_part[0], array('module', 'view', 'view_id'))) {
                $query_string[$ele_part[0]] = $ele_part[1];
            }else{
                $result[$ele_part[0]] = $ele_part[1];
            }
        }

        $result['query'] = $query_string;

        return $result;
    }


    public static function createIdPath($module, $view, $view_id, array $other_list = []): string
    {
        $parameter_constr = [
            "module:".$module,
            "view:".$view,
            "view_id:".$view_id,
        ];
        foreach($other_list as $arg => $value) {
            $parameter_constr[] = $arg.":".$value;
        }

        return "/".join("/", $parameter_constr);
    }


    /**
     * @description create or update url's $request_path by checking $id_path. $new_request_path will return to be updated to item's entity
     * @param string $url_type $module:$view
     * @param string $wanted_request_path
     * @param string $id_path
     * @param string  $redirect_code
     * @return ?string $wanted_request_path or new $request_path if the path already exists
     */
    public function createUrl(string $url_type, string $wanted_request_path, string $id_path, $redirect_code=0) : ?string
    {
        $new_request_path = $this->createUniqueRequestPath($wanted_request_path, $id_path);

        $check_id_path_exist = $this->objUrlModel->getUrlByIdPath($id_path);
        if($check_id_path_exist) {
            $res = $this->objUrlModel->update($check_id_path_exist['id'], [
                'request_path'  => $new_request_path ,
            ]);
        } else {
            $res = $this->objUrlModel->create([
                'url_type'      => $url_type,
                'request_path'  => $new_request_path ,
                'id_path'       => $id_path,
                'redirect_code' => $redirect_code,
            ]);
        }

        return ($res->getStatus() == AppResponse::SUCCESS) ? $new_request_path : null;
    }


    //create a unique request-path
    protected function createUniqueRequestPath(string $wanted_request_path, string $id_path) : string
    {
        $check_exist =  $this->objUrlModel->getUrlByRequestPath($wanted_request_path);

        //ok, can use this one
        if(!$check_exist || $check_exist['id_path'] == $id_path ) {
            return $wanted_request_path;
        }

        //other case, create new path and check again
        $random_suffix = IDGenerator::createStringId(4, true);
        $new_request_path = $wanted_request_path . '-'.$random_suffix;

        return $this->createUniqueRequestPath($new_request_path, $id_path);
    }


}
