<?php

/**
 * +----------------------------------------------------------------------
 * | Created By PhpStorm
 * +----------------------------------------------------------------------
 * | DATE: 2021/7/14
 * +----------------------------------------------------------------------
 * | TIME: 13:06
 * +----------------------------------------------------------------------
 * | Author: YangXing(925032253@qq.com)
 * +----------------------------------------------------------------------
 * | Class: authoritySystem
 * +----------------------------------------------------------------------
 */

namespace model;



/**
 * 后台权限控制
 * Class authoritySystem
 * @package model
 */
class authoritySystem extends \model
{
    /**
     * @var int
     */
    public $userID = 0;

    /**
     * @var bool
     */
    public $isAdmin = false; //管理员

    /**
     * @var bool
     */
    public $isSupperAdmin = false; //超级管理员

    /**
     * @var null
     */
    public $modPower = null;

    /**
     * @var null
     */
    public $allModData = null;

    /**
     * @var null
     */
    public $userModData = null;

    /**
     * @var array
     */
    public $allAction = [];

    /**
     * @var array
     */
    public $userAction = [];

    /**
     * @var int[]|null
     */
    public $tags = null;

    /**
     * @var null
     */
    public $parts = null;

    /**
     * @var null
     */
    public $part_params = null;

    /**
     * @var string[]
     */
    public $temp = [
        'am_view_action'   => 'view',
        'am_add_action'    => 'add',
        'am_edit_action'   => 'edi',
        'am_delete_action' => 'delete',
        'am_import_action' => 'import',
        'am_export_action' => 'export',
        'am_done_action'   => 'done'
    ];

    /**
     * authoritySystem constructor.
     */
    public function __construct()
    {
        $this->db =  new \lib\db();
        $this->tags = [
            'view'   => 1,
            'add'    => 2,
            'edit'   => 4,
            'delete' => 8,
            'import' => 16,
            'export' => 32,
            'done'   => 64
        ];
    }

    /**
     * 绑定用户
     * @return array
     */
    public function bind($userID)
    {
        if(empty($userID)) exit('用户构建权限失败');
        $this->userID = $userID;
        array_map(function ($func){
            $this->$func();
        },['checkAdmin','getAllModData','getUserModData','getModPower']);
    }


    /**
     * 构建权限action
     * @return array
     */
    private function createAction($str,&$action,$type)
    {
//        $arr = explode(',',$str);
//        foreach($arr as $v)
//        {
//            $v = trim($v);
//            if($v!='' && !in_array($v,$action))
//            {
//                if(isset($action[$v])){
//                    $action[$v] = (int)$action[$v] | (int)$this->tags[$type];
//                }else{
//                    $action[$v] = $this->tags[$type];
//                }
//            }
//        }
    }

    /**
     * action是否存在某个权限
     * @param $val string 值 view 或者 1
     * @param $power  [int] 权限的值
     * @return bool
     */
    private function isHasPower($val,$power)
    {
        if(!is_numeric($val)) $val = $this->tags[$val];
        return ((int)$val ^ (int)$power) < (int)$power;
    }

    //判断是否为管理员及级别
    private function checkAdmin()
    {
        if(strcmp($this->userID, \mvc::$cfg['ADMIN_USER']) === 0)
        {
            $this->isAdmin = true;
            $this->isSupperAdmin = true;
        }
        else
        {
            $bool = $this->db->has('gsp_adm_user_link_role',array(
                "ault_ar_id[=]" => 1,
                'ault_au_id[=]' => $this->userID
                )
            );
            if(is_bool($bool) && $bool == true) $this->isAdmin = true;
        }
    }

    /**
     * @param $pt_id
     * @param $mod
     * @param $type
     * @param false $isAll
     * @return bool
     */
    public function m1($ptId,$mod,$type,$isAll=false)
    {
        return ($ptId <=0 ? $this->checkPowerMod($mod,$type,$isAll) : $this->checkPowerMods($ptId,$mod,$type,$isAll));
    }

    /**
     * @param $ptId
     * @param $mod
     * @param $type
     * @param false $isAll
     * @return bool
     */
    public function checkPowerMods($ptId,$mod,$type,$isAll=false)
    {

        if($this->isAdmin) return true;

        $result = false;

        $mods = $mod;

        $types = $type;

        if(!is_array($mods)) $mods = [$mod];

        if(!is_array($types)) $types = [$type];

        foreach($mods as $mod)
        {
            $has = false;

            foreach($types as $type)
            {
                if(!is_numeric($type)) $type = $this->tags[$type];

                if(isset($this->modPower[$mod]) && $this->checkPowerPart($ptId,$type))
                {
                    $has = (((int)$type ^ (int)$this->modPower[$mod]) < (int)$this->modPower[$mod]);

                    if(!$isAll && $has) break;

                    if($isAll && !$has) break;
                }
            }
            $result = $has;

            if(!$result) break;
        }
        return $result;
    }

    //获取全部权限模块数据
    private function getAllModData()
    {
        if(is_null($this->allModData))
        {
            $fields = "*";
            $where = ['am_obj[!]' => 2];
            $this->allModData = $this->db->select("gsp_adm_mod",$fields,$where);

            foreach($this->allModData as $row)
            {
                foreach ($this->temp as $key => $item)
                {
                    $this->createAction($row[$key],$this->allAction,$item);
                }
            }
        }
    }

    /**
     * 获取用户权限模块数据
     * @return array
     */
    private function getUserModData()
    {
        if(is_null($this->userModData))
        {
            $join = [
                "[><]gsp_adm_role_link_mod"  => ["gsp_adm_mod.am_id" => "arlm_am_id"],
                "[><]gsp_adm_user_link_role" => ["gsp_adm_role_link_mod.arlm_ar_id" => "ault_ar_id"]
            ];
            $where = [
                "gsp_adm_user_link_role.ault_au_id[=]" => $this->userID
            ];
            $filed = '*';
            $this->userModData = $this->db->select("gsp_adm_mod",$join,$filed,$where);

            array_map(function ($row){
                $this->addActionPower($row,$this->userAction);
            },$this->userModData);
        }
    }

    /**
     * action权限
     * @param $row
     * @param $arr
     */
    private function addActionPower($row,&$arr)
    {
        foreach ($this->temp as $tags => $action)
        {
            if($this->isHasPower($tags,$row['arlm_power']))
            {
                $this->createAction($row[$action],$this->userAction,$tags);
            }
        }
    }

    //模块权限列表
    private function getModPower()
    {
        $arr = [];
        foreach($this->userModData as $row)
        {
            $amId = $row['am_id'];
            $arr[$amId] = isset($arr[$amId]) ? (int) $arr[$amId] | (int) $row['arlm_power'] : $row['arlm_power'];
        }
        $this->modPower = $arr;
    }

    /**
     * ids权限列表
     * @param $table
     * @return array
     */
    private function getIds($table)
    {
        $join = ["[<>]gsp_adm_user_link_role" => ["ault_ar_id" => "arr_ar_id"]];
        $where = ["arr_table[=]" => $table,'ault_au_id[=]' => $this->userID];
        $table = $this->db->select('gsp_adm_role_link_ids',$join,['*'],$where);
        $arr =[];
        foreach($table as $row)
        {
            $arrPower = $row['arr_power'];
            if(isset($arr[$row['arr_table_id']])){
                $arr[$row['arr_table_id']] = (int)$arr[$row['arr_table_id']] | (int)$arrPower;
            }else{
                $arr[$row['arr_table_id']] = $arrPower;
            }
        }
        return $arr;
    }

    /**
     * 零件权限列表
     * @return string
     */
    private function getPartPower()
    {
        if($this->parts==null) $this->parts=$this->getIds('part');
    }

    /**
     * 参数权限列表
     * @return string
     */
    private function getPartParamPower()
    {
        if($this->part_params==null)  $this->part_params=$this->getIds('part_param');
    }

    /**
     * MD5密码
     * @123456 的值为 15d70fe1e26e7f85df4619f160f832fb
     * @return string
     */
    public function pass($value)
    {
        return md5(substr($value,-3).md5($value.substr($value,0,3)).'^8mR3Hc7&98s5*62Q/');
    }

    /**
     * 登录
     * @return bool
     */
    public function login($userID,$pass)
    {
        $pas = $this->db->get('gsp_adm_user',[
            "[>]object(a)" => ["au_depa" => "o_id"],
            "[>]object(b)" => ["au_area" => "o_id"],
        ],['au_pass','au_depa','au_area','au_dlang','temp','a.cn_name(au_depa_cn_name)','a.en_name(au_depa_en_name)','b.cn_name(au_area_cn_name)','b.en_name(au_area_en_name)'],[
            'au_status[=]' => 1,
            'au_id]' => $userID
        ]);
        $bool = $pas['au_pass'] == $this->pass($pass);
        return $bool ? $pas : false;;
    }

    public function getWorkRole($userId)
    {
        $result = $this->db->select('gsp_adm_user_link_role',[
            '[><]gsp_adm_work_link_role' => ['ault_ar_id' => 'awr_ar_id']
        ],['awr_aw_id','awr_cid'],['ault_au_id' => $userId]);
        return empty($result) ? [] : $result;
    }

    /**
     * 外部登录
     * @return bool
     */
    public function outlogin($outkey)
    {
        return true;
        //TODO 待完成
//        $sql = sprintf("SELECT * FROM `gsp_adm_user` WHERE au_status='on' && md5(au_outid)='%s' limit 1",md5($outkey));
//        $row = self::$db->Row($sql);
//        if($row && isset($row['au_id'])){
//            $_SESSION['logined'] = true;
//            $_SESSION['userID']=$row['au_id'];
//            $_SESSION['user'] = [
//                'user_id' => $row['au_id']
//            ];
//            return true;
//        }
//        return false;
    }

    /**
     * 菜单
     * @return array
     */
    public function getMenu()
    {
        $arr = [];
        $table = ($this->isAdmin) ? $this->allModData : $this->userModData;
        foreach($table as $row)
        {
            $amId = $row['am_id'];

            $menuAction = trim($row['am_menu_action']);

            if(!is_null($menuAction) && $row['am_is_hidden'] == 0)
            {
                if(!isset($arr[$amId]))
                {
                    $menuLang = $row['am_menu_action'];
                    $menuNode = 0;
                    //菜单节点
                    if(!is_null($menuAction)) $menuNode = 2;

                    if(strpos($menuAction,'/') === false)
                    {
                        $menuAction = '';
                        $menuNode = 1;
                    }
                    $arr[$amId] = [
                        'am_id'          => $amId,
                        'am_menu_action' => $menuAction,
                        'menu_node'      => $menuNode,
                        'menu_lang'      => $menuLang,
                        'am_sort'        => $row['am_sort']
                    ];
                }
            }
        }

        $menus = [];

        $parentId = 0;

        foreach($arr as $k => $v)
        {
            if($v['menu_node'] == 1)
            {
                $menus[$k] = [
                    'am_id'     => $v['am_id'],
                    'menu_lang' => $v['menu_lang'],
                    'am_sort'   => $v['am_sort']
                ];
                $parentId = $k;
            }
            else
            {
                $menus[$parentId]['items'][] = [
                    'am_id'          => $v['am_id'],
                    'am_menu_action' => $v['am_menu_action'],
                    'menu_lang'      => $v['menu_lang']
                ];
            }
        }

        $menus = array_column($menus,null,'am_sort');
        ksort($menus);

        return $menus;
    }

    /**
     * 检测action是否拥有权限
     * @return bool
     */
    public function checkPowerAction($class,$method,$params)
    {
        $result = true;
        $action = $class.'/'.$method;

        if(isset($params['func'])) $action.='/?func='.$params['func'];

        if(!$this->isAdmin && isset($this->allAction[$action]))
        {
            //权限表里存在当前类与方法 并且不是管理员
            if(isset($this->userAction[$action])){ //用户存在此方法
                //是否拥有权限
                $result = (int)$this->userAction[$action] ^ (int)$this->allAction[$action] < (int)$this->allAction[$action];
            }else{
                $result = false;
            }
        }
        return $result;
    }

    /**
     * 检测是否拥有模块的指定权限
     * @param $mod string|array 模块编码
     * @param $types  array|string|int] 指定权限 view,add,edit,delete,import,export,done
     * @param $isall bool 为false如果一个type符合就为真，为true需要全部符合
     * @return bool
     */
    public function m($mod,$type,$isall=false)
    { //简写
        return $this->checkPowerMod($mod,$type,$isall);
    }

    /**
     * @param $mod
     * @param $type
     * @param false $isAll
     * @return bool
     */
    public function checkPowerMod($mod,$type,$isAll=false)
    {
        if($this->isAdmin) return true;
        $result = false;
        $mods = $mod;
        $types = $type;
        if(!is_array($mods)) $mods = [$mod];
        if(!is_array($types)) $types = [$type];

        foreach($mods as $mod)
        {
            $has = false;

            foreach($types as $type)
            {
                if(!is_numeric($type)) $type = $this->tags[$type];

                if(isset($this->modPower[$mod]))
                {
                    $has = (((int)$type ^ (int)$this->modPower[$mod]) < (int)$this->modPower[$mod]);
                    if(!$isAll && $has) break;
                    if($isAll && !$has) break;
                }
            }
            $result = $has;
            if(!$result) break;
        }

        return $result;
    }

    /**
     * 检测是否拥有part的指定权限
     * @param $id int 零件ID
     * @param $type string|int 指定权限 view,add,edit,delete,import,export,done
     * @return bool
     */
    public function checkPowerPart($id,$type)
    {
        if($this->isAdmin) return true;
        $result = false;
        $this->getPartPower();
        if($this->parts && isset($this->parts[$id]))
        {
            if(!is_numeric($type)) $type = $this->tags[$type];
            $result = (((int)$type ^ (int)$this->parts[$id]) < (int)$this->parts[$id]);
        }
        return $result;
    }

    /**
     * 检测是否拥有part_param的指定权限
     * @param $id int 参数ID
     * @param $type string|int 指定权限 view,add,edit,delete,import,export,done
     * @return bool
     */
    public function checkPowerPartParam($id,$type)
    {
        if($this->isAdmin) return true;
        $result = false;
        $this->getPartParamPower();
        if($this->part_params && isset($this->part_params[$id]))
        {
            if(!is_numeric($type)) $type = $this->tags[$type];
            $result = (((int)$type ^ (int)$this->part_params[$id]) < (int)$this->part_params[$id]);
        }
        return $result;
    }

    /**
     * 拥有权限的零件总成ID集
     * @param $type string|int 指定权限 view,add,edit,delete,import,export,done
     * @return int|string 管理员返回的是一个sql
     */
    public function getPowerPartGroups($type)
    {
        //TODO
        $result = [];
//        $result = 0;
//        $this->getPartPower();
//        if($this->isAdmin)
//            $result = 'select pg_id from gsp_part_group';
//        else{
//            if($this->parts){
//                $ids = $this->getPowerParts($type);
//                if($ids){
//                    $sql = sprintf("SELECT DISTINCT pg_id FROM `gsp_part_group`
//                                    JOIN `gsp_part` ON pt_pg_id = pg_id
//                                    WHERE pt_id IN (%s);
//                                    ",$ids);
//                    $table = $this->gspDb->Table($sql);
//                    $arr = [];
//                    foreach($table as $row){
//                        $arr[] = $row['pg_id'];
//                    }
//                    if(count($arr)>0)
//                        $result = implode(',',$arr);
//                }
//            }
//        }
        return $result;
    }

    /**
     * 拥有权限的零件ID集
     * @param $type  [string|int] 指定权限 view,add,edit,delete,import,export,done
     * @return string 管理员返回的是一个sql
     */
    public function getPowerParts($type)
    {
//        $result = 0;
//        $this->getPartPower();
//        if($this->isAdmin)
//            $result = 'select pt_id from gsp_part';
//        else{
//            if($this->parts){
//                $arr = [];
//                if(!is_numeric($type)) $type = $this->tags[$type];
//                foreach($this->parts as $k=>$v){
//                    if(((int)$type ^ (int)$v) < (int)$v){
//                        $arr[] = $k;
//                    }
//                }
//                if(count($arr)>0)
//                    $result = implode(',',$arr);
//            }
//        }
//        return $result;
    }

    /**
     * 拥有权限的指定零件的参数ID集
     * @param $type  [string|int] 指定权限 view,add,edit,delete,import,export,done
     * @return string 管理员返回的是一个sql
     */
    public function getPowerPartParams($pt_id,$type)
    {
//        $result = 0;
//        $this->getPartParamPower();
//        if($this->isAdmin)
//            $result = sprintf("select ptpa_id from gsp_part_param where ptpa_pt_id=%d",$pt_id);
//        else{
//            if($this->part_params){
//                $arr = [];
//                if(!is_numeric($type)) $type = $this->tags[$type];
//                $sql = sprintf("select ptpa_id from gsp_part_param where ptpa_pt_id=%d",$pt_id);
//                $table = $this->gspDb->Table($sql);
//                foreach($table as $row){
//                    if(isset($this->part_params[$row['ptpa_id']])){
//                        $v = $this->part_params[$row['ptpa_id']];
//                        if(((int)$type ^ (int)$v) < (int)$v){
//                            $arr[] = $row['ptpa_id'];
//                        }
//                    }
//                }
//                if(count($arr)>0)
//                    $result = implode(',',$arr);
//                else
//                    $result = 0;
//            }
//        }
//        return $result;
    }

    /**
     * @param $data
     * @return bool
     */
    public function addUserLog($data)
    {
        return true;
//        try{
//            $this->gspDb->Insert('gsp_adm_user_log',$data);
//        }catch (Exception $e){
//            return true;
//        }
//        return true;
    }
}
