package org.holer.server.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.reflect.TypeToken;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.holer.common.util.HolerUtil;
import org.holer.server.constant.HolerCode;
import org.holer.server.db.DBClientService;
import org.holer.server.db.DBPortService;
import org.holer.server.db.DBUserService;
import org.holer.server.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

@Component
public class ServerUtil {
    private static final Logger log = LoggerFactory.getLogger(ServerUtil.class);


    @Autowired
    private DBUserService userService;


    @Autowired
    private DBPortService portService;

    @Autowired
    private DBClientService clientService;

    private OkHttpClient httpClient;

    private static Map<Integer, HolerStatus> msg = null;

    private static ApplicationContext appCtx = null;

    private static ServerUtil util;


    @PostConstruct
    public void init() {
        util = this;
        util.userService = this.userService;
        util.clientService = this.clientService;
        util.portService = this.portService;
        util.httpClient = new OkHttpClient();
    }


    public static ServerUtil getInstance() {
        return util;
    }


    public DBUserService getUserService() {
        return this.userService;
    }


    public DBClientService getClientService() {
        return this.clientService;
    }


    public DBPortService getPortService() {
        return this.portService;
    }


    public static void setAppCtx(ApplicationContext appCtx) {
        ServerUtil.appCtx = appCtx;
    }


    public static String property(String key) {
        if (null == appCtx) {
            return "";
        }
        return appCtx.getEnvironment().getProperty(key);
    }


    /**
     * 根据指定的code返回提示信息
     * @param code 提示信息编号
     */
    public static HolerStatus status(Integer code) {
        if (null == msg) {
            String json = "";
            try {
                InputStream is = HolerStatus.class.getClassLoader().getResourceAsStream("conf/message.json");
                json = IOUtils.toString(is, "UTF-8");
                HolerUtil.close(is);
            } catch (IOException e) {
                log.error("读取文件失败: conf/message.json", e.getMessage());
                return null;
            }
            msg = (Map) HolerUtil.toObject(json, new TypeToken<Map<Integer, HolerStatus>>() {});
        }
        if (null == msg || !msg.containsKey(code)) {
            return null;
        }

        HolerStatus status = msg.get(code);
        status.setCode(code);
        status.setMsg(status.getMsgZhCN());
        return status;
    }


    /**
     * 正则验证
     * @param str 要判断的字符串
     * @param regex 格式
     */
    public static boolean isValid(String str, String regex) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }


    /**
     * 判断是否是内网地址
     * @param server 内网地址
     */
    public static HolerCode isValidServer(String server) {
        if (StringUtils.isBlank(server)) {
            return HolerCode.BAD_SERVER;
        }
        if (!isValid(server, "^[0-9a-zA-Z.-:]{3,64}$")) {
            return HolerCode.BAD_SERVER;
        }

        String portStr = StringUtils.substringAfter(server, ":");
        if (StringUtils.isBlank(portStr)) {
            return HolerCode.BAD_SERVER;
        }
        if (!StringUtils.isNumeric(portStr)) {
            return HolerCode.BAD_SERVER;
        }

        int portNum = Integer.parseInt(portStr);
        if (portNum < 1 || portNum > 65535) {
            return HolerCode.BAD_PRIVATE_PORT;
        }
        return HolerCode.OK;
    }



    /**
     * 返回成功的标记
     */
    public static <T> HolerResult success() {
        return new HolerResult(HolerCode.OK);
    }


    /**
     * 返回成功的标记并且携带要返回的数据
     */
    public static <T> HolerResult success(T data) {
        return new HolerResult(data, HolerCode.OK);
    }

    /**
     * 返回错误的标记
     */
    public static <T> HolerResult failure(HolerCode code) {
        return new HolerResult(code);
    }


    /**
     * 打印JSON内容到页面
     */
    public static void write(HttpServletResponse rep, HolerResult<?> result) throws IOException {
        rep.setCharacterEncoding("UTF-8");
        rep.setContentType("application/json;charset=utf-8");
        rep.getWriter().write(HolerUtil.toJson(result));
    }


    /**
     * 验证Token
     */
    public static boolean isValidToken(HttpServletRequest req) {
        String ctoken = req.getHeader("NOSUM-AUTH-TOKEN");
        if (StringUtils.isBlank(ctoken)) {
            return false;
        }
        HttpSession session = req.getSession();
        String stoken = (String) session.getAttribute("NOSUM-AUTH-TOKEN");
        if (StringUtils.isBlank(stoken)) {
            HolerUser dbUser = util.userService.findByToken(ctoken);
            if (null == dbUser || StringUtils.isEmpty(dbUser.getToken())) {
                return false;
            }
            session.setAttribute("NOSUM-AUTH-TOKEN", dbUser.getToken());
            return true;
        }
        if (ctoken.equals(stoken)) {
            return true;
        }
        return false;
    }


    /**
     * 生成随机数
     */
    public static String randomID() {
        String randomID = UUID.randomUUID().toString();
        randomID = StringUtils.replace(randomID, "-", "");
        return randomID.toLowerCase();
    }


    public static String defaultDomain(int portNum) {
        String portStr = "";
        if (portNum >= 1 && portNum <= 65535) {
            portStr = String.valueOf(portNum);
        }
        return String.format("Qing%s.", portStr) + ServerMgr.getDomainName();
    }


    public static <T> T clone(T obj) {
        try {
            T destObj = (T) Class.forName(obj.getClass().getName()).newInstance();
            BeanUtils.copyProperties(destObj, obj);
            return destObj;
        } catch (Exception exception) {


            return null;
        }
    }


    public static <T> T toOject(String content, Class<T> clas) {
        ObjectMapper mapper = new ObjectMapper();

        try {
            return (T) mapper.readValue(content, clas);
        } catch (Exception exception) {


            return null;
        }
    }


    public static long divide(long a, long b) {
        return BigDecimal.valueOf(a).divide(BigDecimal.valueOf(b), 0, 4).longValue();
    }


    public static boolean isWin() {
        String os = System.getProperty("os.name").toLowerCase();
        if (os.startsWith("win")) {
            return true;
        }
        return false;
    }


    /**
     * 验证许可证
     */
    public static HolerResult<?> verifyLicense() {
        String serialNo = ServerMgr.getSerialNo();
        if (StringUtils.isBlank(serialNo)) {
            return new HolerResult(HolerCode.ERR_DEFAULT_MAPPING);
        }
        HolerLicense holerLicense=new HolerLicense();
        holerLicense.setPortNum(Long.MAX_VALUE-10000L);
        holerLicense.setCreateAt(Long.MAX_VALUE-10000L);
        holerLicense.setExpireAt("9223372036854775807");
        holerLicense.setLicenseId(1L);
        holerLicense.setPortNum(Long.MAX_VALUE-10000L);
        holerLicense.setValidDay(Long.MAX_VALUE-10000L);
        holerLicense.setUserName("noSum");
        return new HolerResult<HolerLicense>(1000);
    }
}