package com.dji.sample.common.util;

import com.auth0.jwt.interfaces.DecodedJWT;
import com.dji.sample.common.model.CustomClaim;
import com.dji.sample.manage.model.enums.RoleTypeEnum;
import com.dji.sample.manage.model.enums.UserTypeEnum;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

import static com.dji.sample.component.AuthInterceptor.PARAM_TOKEN;

/**
 * @author guan
 */
public class SecurityUtils {

    /**
     * 生成BCryptPasswordEncoder密码
     *
     * @param password 密码
     * @return 加密字符串
     */
    public static String encryptPassword(String password) {
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        return passwordEncoder.encode(password);
    }

    /**
     * 判断密码是否相同
     *
     * @param rawPassword 真实密码
     * @param encodedPassword 加密后字符
     * @return 结果
     */
    public static boolean matchesPassword(String rawPassword, String encodedPassword) {
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        return passwordEncoder.matches(rawPassword, encodedPassword);
    }

    /**
     * 判断当前用户是否admin
     * @return
     */
    public static boolean isAdmin() {

        DecodedJWT jwt = JwtUtil.verifyToken(getToken());
        CustomClaim customClaim = new CustomClaim(jwt.getClaims());

        Integer userType = customClaim.getUserType();
        if (userType == null) {
            return false;
        }

        return userType == UserTypeEnum.WEB.getVal();
    }

    public static boolean isNotAdmin() {
        return !isAdmin();
    }

    /**
     * 获取token
     * @return
     */
    public static String getToken() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        return request.getHeader(PARAM_TOKEN);
    }

    public static Integer getRoleType() {
        DecodedJWT jwt = JwtUtil.verifyToken(getToken());
        CustomClaim customClaim = new CustomClaim(jwt.getClaims());

        return customClaim.getRoleType();
    }

    public static String getWorkspaceId() {
        DecodedJWT jwt = JwtUtil.verifyToken(getToken());
        CustomClaim customClaim = new CustomClaim(jwt.getClaims());

        return customClaim.getWorkspaceId();
    }

    public static String getUserId() {
        DecodedJWT jwt = JwtUtil.verifyToken(getToken());
        CustomClaim customClaim = new CustomClaim(jwt.getClaims());

        return customClaim.getId();
    }

    public static String getUsername() {
        DecodedJWT jwt = JwtUtil.verifyToken(getToken());
        CustomClaim customClaim = new CustomClaim(jwt.getClaims());

        return customClaim.getUsername();
    }


    public static boolean isSysAdminRole() {
        Integer roleType = getRoleType();
        return isSysAdminRole(roleType);
    }

    public static boolean isNotSysAdminRole() {
        return !isSysAdminRole();
    }

    public static boolean isSysAdminRole(Integer roleType) {
        return roleType == RoleTypeEnum.SYS_ADMIN.getVal();
    }

    public static boolean isNotSysAdminRole(Integer roleType) {
        return !isSysAdminRole(roleType);
    }

    public static boolean isAdminRole() {
        Integer roleType = getRoleType();
        return isAdminRole(roleType);
    }

    public static boolean isNotAdminRole() {
        return !isAdminRole();
    }

    public static boolean isProjectAdminRole(Integer roleType) {
        return roleType == RoleTypeEnum.ORG_ADMIN.getVal();
    }

    public static boolean isNotProjectAdminRole(Integer roleType) {
        return !isProjectAdminRole(roleType);
    }

    public static boolean isProjectAdminRole() {
        Integer roleType = getRoleType();
        return isProjectAdminRole(roleType);
    }

    public static boolean isNotProjectAdminRole() {
        return !isProjectAdminRole();
    }

    public static boolean isAdminRole(Integer roleType) {
        return roleType == RoleTypeEnum.ADMIN.getVal();
    }

    public static boolean isNotAdminRole(Integer roleType) {
        return !isAdminRole(roleType);
    }

    public static boolean isPilotRole() {
        Integer roleType = getRoleType();
        return isPilotRole(roleType);
    }

    public static boolean isNotPilotRole() {
        return !isPilotRole();
    }
    public static boolean isPilotRole(Integer roleType) {
        return roleType == RoleTypeEnum.PILOT.getVal();
    }

    public static boolean isNotPilotRole(Integer roleType) {
        return !isPilotRole(roleType);
    }

    public static boolean isMemberRole() {
        Integer roleType = getRoleType();
        return isMemberRole(roleType);
    }

    public static boolean isNotMemberRole() {
        return !isMemberRole();
    }
    public static boolean isMemberRole(Integer roleType) {
        return roleType == RoleTypeEnum.MEMBER.getVal();
    }

    public static boolean isNotMemberRole(Integer roleType) {
        return !isMemberRole(roleType);
    }

    public static boolean aboveMemberRoleAndThrowError() {
        boolean result = aboveMemberRole();
        if (!result) {
            throw new RuntimeException("The current role has no permissions");
        }
        return true;
    }

    public static boolean aboveMemberRole() {
        Integer roleType = getRoleType();
        return aboveMemberRole(roleType);
    }
    public static boolean aboveMemberRole(Integer roleType) {
        int[] roleArr = {RoleTypeEnum.MEMBER.getVal(), RoleTypeEnum.PILOT.getVal(), RoleTypeEnum.ADMIN.getVal(), RoleTypeEnum.ORG_ADMIN.getVal(), RoleTypeEnum.SYS_ADMIN.getVal()};

        for(int role : roleArr){
            if(roleType == role) {
                return true;
            }
        }
        return false;
    }

    public static boolean abovePilotRoleAndThrowError() {
        boolean result = abovePilotRole();
        if (!result) {
            throw new RuntimeException("The current role has no permissions");
        }
        return true;
    }

    public static boolean abovePilotRole() {
        Integer roleType = getRoleType();
        return abovePilotRole(roleType);
    }

    public static boolean abovePilotRole(Integer roleType) {
        int[] roleArr = {RoleTypeEnum.PILOT.getVal(), RoleTypeEnum.ADMIN.getVal(), RoleTypeEnum.ORG_ADMIN.getVal(), RoleTypeEnum.SYS_ADMIN.getVal()};

        for(int role : roleArr){
            if(roleType == role) {
                return true;
            }
        }
        return false;
    }

    public static boolean aboveAdminRoleAndThrowError() {
        boolean result = aboveAdminRole();
        if (!result) {
            throw new RuntimeException("The current role has no permissions");
        }
        return true;
    }

    public static boolean aboveAdminRole() {
        Integer roleType = getRoleType();
        return aboveAdminRole(roleType);
    }

    public static boolean aboveAdminRole(Integer roleType) {
        int[] roleArr = {RoleTypeEnum.ADMIN.getVal(), RoleTypeEnum.ORG_ADMIN.getVal(), RoleTypeEnum.SYS_ADMIN.getVal()};

        for(int role : roleArr){
            if(roleType == role) {
                return true;
            }
        }
        return false;
    }

    public static boolean aboveProjectAdminRoleAndThrowError() {
        boolean result = aboveProjectAdminRole();
        if (!result) {
            throw new RuntimeException("The current role has no permissions");
        }
        return true;
    }

    public static boolean aboveProjectAdminRole() {
        Integer roleType = getRoleType();
        return aboveSysAdminRole(roleType);
    }

    public static boolean aboveProjectAdminRole(Integer roleType) {
        int[] roleArr = {RoleTypeEnum.ORG_ADMIN.getVal(), RoleTypeEnum.SYS_ADMIN.getVal()};

        for(int role : roleArr) {
            if(roleType == role) {
                return true;
            }
        }
        return false;
    }

    public static boolean aboveSysAdminRoleAndThrowError() {
        boolean result = aboveSysAdminRole();
        if (!result) {
            throw new RuntimeException("The current role has no permissions");
        }
        return true;
    }

    public static boolean aboveSysAdminRole() {
        Integer roleType = getRoleType();
        return aboveSysAdminRole(roleType);
    }

    public static boolean aboveSysAdminRole(Integer roleType) {
        int[] roleArr = {RoleTypeEnum.SYS_ADMIN.getVal()};

        for(int role : roleArr) {
            if(roleType == role) {
                return true;
            }
        }
        return false;
    }

}
