<?php

class access
{
    public static function check(string $_element)
    {
        // Eléments autorisé sans authentification
        if (self::checkAccessWhite($_element)) {
            return TRUE;
        } else {
            if (session::isConnect("salarie") and session::isEspaceSalaries()) { // Espaces spécifiques aux Salariés
                return TRUE;
            } elseif (session::isConnect() and session::getType() == 2 and session::isEspaceControleurs()) { // Espaces spécifiques aux Contrôleurs
                return TRUE;
            } else {
                return self::ifAccesss($_element);
            }
        }
    }

    public static function checkAccessOffLine(string $_string)
    {
        return in_array($_string, OFF_LINE);
    }

    public static function checkAccessWhite(string $_string)
    {
        return in_array($_string, WHITE_ACCESS);
    }

    public static function getAccessList(int $_idType = NULL)
    {
        ($_idType == NULL) ? $idType = session::getType() : $idType = $_idType;
        $return["access"] = $return["noAccess"] = $return["exception"] = array();

        db::query("SELECT "
            . "" . DB_T_ACCESS . ".id, "
            . "" . DB_T_ACCESS . ".label, "
            . "" . DB_T_ACCESS . ".access, "
            . "" . DB_T_ACCESS . ".noAccess, "
            . "" . DB_T_TYPE_ACCESS . ".exception "
            . "FROM " . DB_T_TYPE_ACCESS . " "
            . "INNER JOIN " . DB_T_ACCESS . " ON " . DB_T_TYPE_ACCESS . ".id_access = " . DB_T_ACCESS . ".id "
            . "WHERE " . DB_T_TYPE_ACCESS . ".id_type = :id_type ");
        db::bind(':id_type', $idType);

        try {
            $tmp = db::resultset();
            foreach ($tmp as $access) {
                $return["access"] = self::addInArray($access["access"], $return["access"]);
                $return["noAccess"] = self::addInArray($access["noAccess"], $return["noAccess"]);
                if(isset($access["exception"])) { $return["exception"] = self::addInArray($access["exception"], $return["exception"]); }
            }

            // Je supprime les restriction d'accès en fonction des accès accordés
            $return["noAccess"] = array_diff($return["noAccess"], $return["access"]);
            
            return $return;
        } catch (Exception $e) {
            return FALSE;
        }
    }

    public static function getAccessByType()
    {
        $return = array();
        db::query("SELECT "
            . "" . DB_T_TYPE_USER . ".type, "
            . "" . DB_T_ACCESS . ".label, "
            . "" . DB_T_ACCESS . ".show, "
            . "" . DB_T_ACCESS . ".add "
            . "FROM " . DB_T_ACCESS . " "
            . "INNER JOIN " . DB_T_TYPE_USER . " ON " . DB_T_TYPE_USER . ".id = " . DB_T_TYPE_ACCESS . ".id_type "
            . "INNER JOIN " . DB_T_TYPE_ACCESS . " ON " . DB_T_ACCESS . ".id = " . DB_T_TYPE_ACCESS . ".id_access");
        try {
            $tmp = db::resultset();

            foreach ($tmp as $access) {
                $return[$access["type"]][$access["label"]] = array(
                    "show" => $access["show"],
                    "add" => $access["add"],
                );
            }

            return $return;
        } catch (Exception $e) {
            return FALSE;
        }
    }

    public static function getTypesAccess()
    {
        db::query("SELECT "
            . "" . DB_T_ACCESS . ".label, "
            . "" . DB_T_ACCESS . ".show, "
            . "" . DB_T_ACCESS . ".add "
            . "FROM " . DB_T_ACCESS);
        try {
            $tmp = db::resultset();
            return $tmp;
        } catch (Exception $e) {
            return FALSE;
        }
    }

    public static function getTypesUsers(bool $_expect = FALSE)
    {
        $except = ($_expect == FALSE) ? NULL : " WHERE " . DB_T_TYPE_USER . ".id != 1 AND " . DB_T_TYPE_USER . ".id != 2";

        db::query("SELECT * FROM " . DB_T_TYPE_USER . $except);
        try {
            $tmp = db::resultset();
            return $tmp;
        } catch (Exception $e) {
            return FALSE;
        }
    }

    public static function getArrayTypes()
    {
        $return = $final = array();
        $getTypesUsers = self::getTypesUsers(TRUE);

        db::query("SELECT "
            . "CONCAT(" . DB_T_ACCESS . ".label, '|', " . DB_T_ACCESS . ".show, " . DB_T_ACCESS . ".add) AS access, "
            . "" . DB_T_TYPE_ACCESS . ".id_type, "
            . "" . DB_T_TYPE_ACCESS . ".exception, "
            . "" . DB_T_TYPE_USER . ".type "
            . "FROM " . DB_T_ACCESS . " "
            . "LEFT JOIN " . DB_T_TYPE_ACCESS . " ON " . DB_T_TYPE_ACCESS . ".id_access = " . DB_T_ACCESS . ".id "
            . "LEFT JOIN " . DB_T_TYPE_USER . " ON " . DB_T_TYPE_ACCESS . ".id_type = " . DB_T_TYPE_USER . ".id "
        );

        try {
            $tmp = db::resultset();

            foreach ($tmp as $access) {
            
                    $tmpaccess = explode("|", $access["access"]);

                    if($tmpaccess[1] == "10"){
                        $return[$access["access"]]["access"] = "Accès à " . $tmpaccess[0] . " en lecture";
                    } elseif($tmpaccess[1] == "01"){
                        $return[$access["access"]]["access"] = "Accès à " . $tmpaccess[0] . " en écriture";
                    } else {
                        $return[$access["access"]]["access"] = "Accès à " . $tmpaccess[0] . " en lecture et écriture";
                    }

                    foreach ($getTypesUsers as $type) { 
                        if (empty($return[$access["access"]][$type["type"]])) {
                            if ($type["id"] == $access["id_type"]) {
                                if(is_null($access["exception"])){
                                    $return[$access["access"]][$type["type"]] = 1;
                                } else {
                                    $return[$access["access"]][$type["type"]] = 2; 
                                }
                            } 
                            else {
                                $return[$access["access"]][$type["type"]] = 0;
                            }
                        } 
                    }
                        $return[$access["access"]]["Administrateur"] = 1;
                }

                foreach ($return as $value) {
                    $final[] = $value;
                }
            return $final;
        } catch (Exception $e) {
            return FALSE;
        }
    }

    public static function ifLimitAccessException(string $_exception)
    {
        $accessList = self::getAccessList(session::getType());
        return in_array($_exception, $accessList["exception"]) ? TRUE : FALSE;
    }

    public static function ifAccesss(string $_accessAsk, int $_idType = NULL)
    {
        if (session::isConnect() == FALSE and self::checkAccessOffLine($_accessAsk)) {
            return TRUE;
        }

        // Si Admin OK
        $idType = $_idType == NULL ? session::getType() : $_idType;
        if ($idType == 1) {
            return TRUE;
        } 
        // Si Admin OK

        $accessList = self::getAccessList($idType);

        $cheminGenrique = self::checkGenericAccess($_accessAsk, $accessList["access"]);
        if ($cheminGenrique != FALSE AND !in_array($_accessAsk, $accessList["noAccess"])) { // Si Accès générique
            return TRUE;
        } elseif (in_array($_accessAsk, $accessList["access"]) or self::checkAccessWhite($_accessAsk)) {
            return TRUE;
        } else {
            return FALSE;
        }
    }

    private static function checkGenericAccess(string $_string, array $_access_list)
    {
        $string = explode("-", $_string)[0];
        $check = in_array($string."*", $_access_list);
        return ($check == TRUE) ? $string : FALSE;
    }

    private static function getGenericAccess(string $_string)
    {
        return explode("*", $_string);
    }

    private static function splitAccess(string $_string)
    {
        $return = array();
        $tmp = array_filter(explode("\n", $_string));
        foreach ($tmp as $key => $value) {
            $return[$key] = trim($value);
        }
        return $return;
    }

    private static function addInArray(string $_string, array $_array)
    {
        return array_unique(array_merge(self::splitAccess($_string), $_array));
    }
}
