using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using RFrameGenerate.Common;
using RFrameGenerate.DAL;
using RFrameGenerate.Model;
using System.Web.Caching;
using RFramework.SQLServer;
using System.ComponentModel;
using System.Reflection;

namespace RFrameGenerate.BLL
{
    /// <summary>
    /// 权限管理
    /// </summary>
    public class PermissionManage
    {
        /// <summary>
        /// 根据当前登录的用户 权限码 判断用户是否具有当前的权限
        /// </summary>
        /// <param name="type">权限码类型</param>
        /// <returns></returns>
        public bool IsPermission(Type type)
        {
            if (CurrentManage.LoginType == DictionaryConst.LoginType.Merchant || CurrentManage.LoginType == DictionaryConst.LoginType.HeadOffice || CurrentManage.LoginType == DictionaryConst.LoginType.Agent)
                return true;//商家有所有权限

            string permissionCode;
            object[] tables = type.GetCustomAttributes(typeof(RemarkAttribute), true);
            if (tables.Length > 0)
                permissionCode = ((RemarkAttribute)(tables[0])).Value;
            else
                permissionCode = ((RemarkAttribute)Activator.CreateInstance(typeof(RemarkAttribute))).Value;
            return IsPermission(CurrentUser.GetCurrUserGuid(), permissionCode);
        }
        /// <summary>
        /// 根据当前登录的用户 权限码 判断用户是否具有当前的权限
        /// </summary>
        /// <param name="permissionCode">权限码</param>
        /// <returns></returns>
        public bool IsPermission(string permissionCode)
        {
            if (CurrentManage.LoginType == DictionaryConst.LoginType.Merchant || CurrentManage.LoginType == DictionaryConst.LoginType.HeadOffice || CurrentManage.LoginType == DictionaryConst.LoginType.Agent)
                return true;//商家有所有权限

            return IsPermission(CurrentUser.GetCurrUserGuid(), permissionCode);
        }
        /// <summary>
        /// 根据当前登录的用户 权限码 判断用户是否具有当前的权限
        /// </summary>
        /// <param name="userguid">用户GUID</param>
        /// <param name="permissionCode">权限码</param>
        /// <returns></returns>
        private bool IsPermission(Guid userguid, string permissionCode)
        {
            if (CurrentManage.LoginType == DictionaryConst.LoginType.Merchant || CurrentManage.LoginType == DictionaryConst.LoginType.HeadOffice || CurrentManage.LoginType == DictionaryConst.LoginType.Agent)
                return true;//商家有所有权限

            List<string> codeList = GetCachePermission(userguid);
            if (permissionCode == PCode.NoPermission || codeList.Contains(PCode.NoPermission))
            {
                return true;
            }
            return codeList.Any(s => s == permissionCode);
        }
        /// <summary>
        ///  如果权限码字符串为空则默认 不需要权限，直接返回true
        /// </summary>
        /// <param name="userguid"></param>
        /// <param name="permissionCodeList"></param>
        /// <returns></returns>
        public bool IsPermission(Guid userguid, List<string> permissionCodeList)
        {
            if (CurrentManage.LoginType == DictionaryConst.LoginType.Merchant || CurrentManage.LoginType == DictionaryConst.LoginType.HeadOffice || CurrentManage.LoginType == DictionaryConst.LoginType.Agent)
                return true;//商家有所有权限

            List<string> codeList = GetCachePermission(userguid);
            if (permissionCodeList.Contains(PCode.NoPermission) || codeList.Contains(PCode.NoPermission))
            {
                return true;
            }
            foreach (var item in permissionCodeList)
            {
                if (codeList.Any(s => s == item))
                {
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// 根据当前用户从缓存中获取权限
        /// </summary>
        /// <param name="userguid">当前用户</param>
        /// <returns></returns>
        private List<string> GetCachePermission(Guid userguid)
        {
            string keyName = "_Cache_Permission_" + userguid;
            //从缓存中根据键读取，并使用as转换
            List<string> Cache_Permission = HttpContext.Current.Cache[keyName] as List<string>;
            if (HttpContext.Current.Cache["Monitor_Permission"] == null)
                HttpContext.Current.Cache["Monitor_Permission"] = 1;
            if (Cache_Permission == null || Cache_Permission.Count == 0)
            {
                List<string> data = new List<string>();
                data = GetUserPerssionCode(userguid);
                string[] cacheKeys = { "Monitor_Permission" };
                CacheDependency dependency = new CacheDependency(null, cacheKeys);
                //创建缓存
                HttpContext.Current.Cache.Add(keyName, data, dependency, Cache.NoAbsoluteExpiration, new TimeSpan(0, 30, 0), CacheItemPriority.Default, null);
                Cache_Permission = HttpContext.Current.Cache[keyName] as List<string>;
            }
            return (Cache_Permission == null) ? new List<string>() : Cache_Permission;





        }
        /// <summary>
        /// 从数据库中读取当前用户的权限信息
        /// </summary>
        /// <param name="userguid">当前用户</param>
        /// <returns>权限码列表</returns>
        public List<string> GetUserPerssionCode(Guid UserGuid)
        {
            //统一封装时要用view查询 待定
            var list = new List<string>();
            using (SqlRTransaction tan = new SqlRTransaction())
            {
                var queryur = Factory.CreateT_ST_User_Role(tan);
                var queryrp = Factory.CreateT_ST_Role_Permission(tan);

                var r_userRole = queryur.GetList(s => s.UserGuid == UserGuid);
                foreach (var v in r_userRole)
                {
                    list = queryrp.GetList(s => s.RoleGuid == v.RoleGuid).Select(s => s.PermissionCode).ToList();
                }
            }
            list = list.Distinct().ToList();
            return list;
        }
        /// <summary>
        /// 从数据库中读取当前角色的权限信息
        /// </summary>
        /// <param name="userguid">当前用户角色</param>
        /// <returns>权限码列表</returns>
        public List<string> GetRolePerssionCode(Guid roleguid)
        {
            var list = new List<string>();
            using (SqlRTransaction tan = new SqlRTransaction())
            {
                var queryur = Factory.CreateT_ST_Role(tan);
                var queryrp = Factory.CreateT_ST_Role_Permission(tan);

                var r_userRole = queryur.GetList(s => s.RoleGuid == roleguid).First();

                list.AddRange(queryrp.GetList(s => s.RoleGuid == r_userRole.RoleGuid).Select(s => s.PermissionCode.Trim()).ToList());
            }
            return list;
        }


        public static void ClearCachePermission()
        {
            List<string> cacheKeys = new List<string>();
            System.Collections.IDictionaryEnumerator cacheEnum = HttpContext.Current.Cache.GetEnumerator();
            while (cacheEnum.MoveNext())
            {
                cacheKeys.Add(cacheEnum.Key.ToString());
            }
            foreach (string cacheKey in cacheKeys)
            {
                HttpContext.Current.Cache.Remove(cacheKey);
            }

        }

        #region 权限树

        public string GetInitPermissionTree()
        {
            return GenerateTree(new List<string>(), 1);
        }

        //对角色权限控制
        public string GenerateOperateTreeByRole(Guid roleGuid)
        {
            return GenerateTree(GetRolePerssionCode(roleGuid), DictionaryConst.PermissionType.Operate);
        }

        private string GenerateTree(List<string> permissionList, int permissionType)
        {

            List<T_ST_Permission> typePermissionList = new List<T_ST_Permission>();

            using (var query = Factory.CreateT_ST_Permission())
            {
                typePermissionList = query.GetList(null, false, s => s.PermissionCode);
            }

            string treeData = "[";

            foreach (T_ST_Permission permission in typePermissionList)
            {
                string parentId = (!string.IsNullOrEmpty(permission.ParentPermissionCode)) ? permission.ParentPermissionCode : "0";


                if (permissionList.Count(s => s == permission.PermissionCode) > 0)
                {
                    ;
                }
                if (permissionList.Any(s => s == permission.PermissionCode))
                {
                    treeData += "{ id:" + permission.PermissionCode + ", pId:" + parentId +
                        ", name:\"" + permission.PermissionName + "\",checked:true , open:true },";
                }
                else
                {
                    treeData += "{ id:" + permission.PermissionCode + ", pId:" + parentId +
                       ", name:\"" + permission.PermissionName + "\",checked:false , open:true },";
                }
            }
            return treeData.Substring(0, treeData.Length - 1) + "]";
        }

        /// <summary>
        /// 更新权限数据到用户
        /// </summary>
        /// <param name="guid">用户的GUID编号</param>
        /// <param name="checkNodesPCode">选中的权限编码</param>
        /// <returns></returns>
        public bool UpdatePermission(Guid roleGuid, string[] checkNodesPCode)
        {
            try
            {
                List<T_ST_Role_Permission> list = new List<T_ST_Role_Permission>();
                using (SqlRTransaction tan = new SqlRTransaction())
                {
                    tan.BeginTransaction();
                    var query = Factory.CreateT_ST_Role_Permission(tan);
                    var queryPermission = Factory.CreateT_ST_Permission(tan);
                    List<T_ST_Permission> permissionList = new List<T_ST_Permission>();
                    permissionList = queryPermission.GetList();

                    if (checkNodesPCode != null)
                    {
                        foreach (var item in checkNodesPCode)
                        {
                            //用户权限关系表中只保存非父节点的数据

                            if (!permissionList.Where(s => s.ParentPermissionCode == item).Any())
                            {
                                T_ST_Role_Permission userPermission = new T_ST_Role_Permission();
                                userPermission.PermissionCode = item.Trim();
                                userPermission.Role_PermissionGuid = Guid.NewGuid();
                                //userPermission.PermissionGuid = permissionList.First(s => s.PermissionCode == item).PermissionGuid;
                                userPermission.RoleGuid = roleGuid;
                                userPermission.EntityState = EntityStates.ToBeAdd;
                                list.Add(userPermission);
                            }
                        }
                    }

                    var listed = query.GetList(s => s.RoleGuid == roleGuid);
                    for (var i = 0; i < listed.Count(); i++)
                    {
                        listed[i].EntityState = EntityStates.ToBeDelete;
                    }

                    list.AddRange(listed);
                    query.UpdateList(list);

                    tan.Commit();
                }

                //clear cache
                if (HttpContext.Current.Cache["Monitor_Permission"] == null)
                {

                    HttpContext.Current.Cache["Monitor_Permission"] = 1;
                }
                else
                {
                    int currnum = ((int)HttpContext.Current.Cache["Monitor_Permission"] > 10000) ? 1 : (int)HttpContext.Current.Cache["Monitor_Permission"];
                    HttpContext.Current.Cache["Monitor_Permission"] = currnum + 1;
                }
                return true;
            }
            catch (Exception e)
            {
                return false;
            }
        }


        #endregion

        /// <summary>
        /// 根据权限码添加系统所有权限到数据库
        /// </summary>
        public static void AddPerssionCodeDatabase()
        {
            using (var tran = new SqlRTransaction())
            {
                //添加权限
                var queryPer = Factory.CreateT_ST_Permission(tran);
                List<T_ST_Permission> dblist = queryPer.GetList();
                List<T_ST_Permission> newlist = GetPermissionFormPCode();
                List<T_ST_Permission> addlist = new List<T_ST_Permission>();
                foreach (var v in newlist)
                {
                    var per = dblist.Where(a => a.PermissionCode == v.PermissionCode).FirstOrDefault();
                    if (per == null)
                    {
                        v.EntityState = EntityStates.ToBeAdd;
                        addlist.Add(v);
                    }
                    else
                    {
                        if (per.PermissionName != v.PermissionName)
                        {
                            per.PermissionName = v.PermissionName;
                            per.EntityState = EntityStates.ToBeUpdated;
                            addlist.Add(per);
                        }
                    }
                }
                queryPer.UpdateList(addlist);
                //tran.BeginTransaction();

                ////添加管理员
                //var queryUser = Factory.CreateT_ST_User(tran);
                //var admin = queryUser.GetFirstData(a => a.UserGuid == CurrentUser.AdminIdentification);
                //if (admin == null)
                //{
                //    admin = new T_ST_User() { UserGuid = CurrentUser.AdminIdentification, LoginName = "admin", UserName = "管理员", Password = Utils.Md5("123456"), Remark = "管理员" };
                //    queryUser.Add(admin);

                //    //添加角色
                //    var queryRole = Factory.CreateT_ST_Role(tran);
                //    var role = queryRole.GetFirstData(a => a.RoleName == "管理员");
                //    if (role == null)
                //    {
                //        role = new T_ST_Role() { RoleGuid = Guid.NewGuid(), RoleName = "管理员", RoleCode = AutoCodeBLL.GetAutoRoleCode(), RoleRemark = "管理员角色" };
                //        queryRole.Add(role);
                //    }
                //    //关联角色和权限
                //    var queryrRolePer = Factory.CreateT_ST_Role_Permission(tran);
                //    var rolePer = queryrRolePer.GetFirstData(a => a.PermissionCode == PCode.NoPermission);
                //    if (rolePer == null)
                //    {
                //        rolePer = new T_ST_Role_Permission() { Role_PermissionGuid = Guid.NewGuid(), PermissionCode = PCode.NoPermission, PermissionGuid = newlist.Where(a => a.PermissionCode == PCode.NoPermission).FirstOrDefault().PermissionGuid, RoleGuid = role.RoleGuid };
                //        queryrRolePer.Add(rolePer);
                //    }
                //    //关联管理员和角色
                //    var queryUserRole = Factory.CreateT_ST_User_Role(tran);
                //    var userRole = queryUserRole.GetFirstData(a => a.UserGuid == admin.UserGuid);
                //    if (userRole == null)
                //    {
                //        userRole = new T_ST_User_Role() { UserGuid = admin.UserGuid, RoleGuid = role.RoleGuid, User_RoleGuid = Guid.NewGuid() };
                //        queryUserRole.Add(userRole);
                //    }
                //    tran.Commit();
                //}
            }
        }
        /// <summary>
        /// 获取系统所有权限码
        /// </summary>
        /// <returns></returns>
        public static List<T_ST_Permission> GetPermissionFormPCode()
        {
            List<T_ST_Permission> list = new List<T_ST_Permission>();
            PCode code = new PCode();
            Type type = code.GetType();
            var members = type.GetMembers(BindingFlags.Public | BindingFlags.Static);
            string value = string.Empty;
            RemarkAttribute attribute;
            foreach (var mem in members)
            {
                switch (mem.MemberType)
                {
                    case MemberTypes.Field:
                        value = ((FieldInfo)mem).GetValue(code).ToString();
                        attribute = mem.GetCustomAttributes(true)[0] as RemarkAttribute;
                        list.Add(GetNewModel("0", value, attribute.Remark));
                        break;
                    case MemberTypes.NestedType:
                        attribute = mem.GetCustomAttributes(true)[0] as RemarkAttribute;
                        list.Add(GetNewModel("0", attribute.Value, attribute.Remark));
                        string moduleName = type.Module.Name.Substring(0, type.Module.Name.Length - 4);
                        var v = Assembly.Load(moduleName).CreateInstance(mem.ReflectedType.FullName + "+" + mem.Name);
                        ForeachCode(list, v.GetType(), attribute.Value, moduleName);
                        break;
                }
            }
            return list;
        }
        private static void ForeachCode(List<T_ST_Permission> list, Type type, string parentCode, string moduleName)
        {
            object code = Activator.CreateInstance(type);
            var members = type.GetMembers(BindingFlags.Public | BindingFlags.Static);
            string value = string.Empty;
            RemarkAttribute attribute;
            foreach (var mem in members)
            {
                switch (mem.MemberType)
                {
                    case MemberTypes.Field:
                        value = ((FieldInfo)mem).GetValue(code).ToString();
                        attribute = mem.GetCustomAttributes(true)[0] as RemarkAttribute;
                        list.Add(GetNewModel(parentCode,/*parentCode + */ value, attribute.Remark));
                        break;
                    case MemberTypes.NestedType:
                        attribute = mem.GetCustomAttributes(true)[0] as RemarkAttribute;
                        list.Add(GetNewModel(parentCode,/*parentCode + */ attribute.Value, attribute.Remark));
                        var v = Assembly.Load(moduleName).CreateInstance(mem.ReflectedType.FullName + "+" + mem.Name);
                        ForeachCode(list, v.GetType(), /*parentCode + */ attribute.Value, moduleName);
                        break;
                }
            }
        }

        private static T_ST_Permission GetNewModel(string parentCode, string code, string name)
        {
            return new T_ST_Permission()
                        {
                            PermissionGuid = Guid.NewGuid(),
                            ParentPermissionCode = parentCode,
                            PermissionCode = code,
                            PermissionName = name,
                            PermissionType = 0
                        };
        }
    }
}
