package com.cm.central.control.service.client.impl;

import com.cm.central.control.manager.SocketServerManager;
import com.cm.central.control.pojo.bos.ClientBO;
import com.cm.central.control.pojo.bos.SocketClientBO;
import com.cm.central.control.pojo.dtos.client.ClientLicenseAuthorizationDTO;
import com.cm.common.base.AbstractService;
import com.cm.common.constants.ISystemConstant;
import com.cm.common.exception.RemoveException;
import com.cm.common.exception.SearchException;
import com.cm.common.pojo.ListPage;
import com.cm.common.result.SuccessResult;
import com.cm.common.result.SuccessResultData;
import com.cm.common.result.SuccessResultList;
import com.cm.common.utils.AesUtil;
import com.cm.common.utils.HashMapUtil;
import com.cm.common.utils.MD5Util;
import com.cm.common.utils.UUIDUtil;
import com.cm.central.control.dao.client.IClientDao;
import com.cm.central.control.pojo.dtos.client.ClientDTO;
import com.cm.central.control.pojo.vos.client.ClientVO;
import com.cm.central.control.service.client.IClientService;
import com.cm.security.License;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @ClassName: ClientServiceImpl
 * @Description: 客户端
 * @Author: WenG
 * @Date: 2020-07-30 19:12
 * @Version: 1.0
 **/
@Service
public class ClientServiceImpl extends AbstractService implements IClientService {

    @Autowired
    private IClientDao clientDao;

    @Override
    public SuccessResult saveClient(ClientVO clientVO) throws Exception {
        saveClientInfo(null, clientVO);
        return new SuccessResult();
    }

    @Override
    public SuccessResult saveClientByToken(String token, ClientVO clientVO) throws Exception {
        saveClientInfo(token, clientVO);
        return new SuccessResult();
    }

    @Override
    public String saveClientReturnId(ClientVO clientVO) throws Exception {
        return saveClientInfoReturnId(null, clientVO);
    }

    @Override
    public String saveClientByTokenReturnId(String token, ClientVO clientVO) throws Exception {
        return saveClientInfoReturnId(token, clientVO);
    }

    /**
     * 新增客户端
     *
     * @param token
     * @param clientVO
     * @throws Exception
     */
    private void saveClientInfo(String token, ClientVO clientVO) throws Exception {
        saveClientInfoReturnId(token, clientVO);
    }

    /**
     * 新增客户端
     *
     * @param token
     * @param clientVO
     * @return clientId
     * @throws Exception
     */
    private String saveClientInfoReturnId(String token, ClientVO clientVO) throws Exception {
        String clientId = UUIDUtil.getUUID();
        Map<String, Object> params = HashMapUtil.beanToMap(clientVO);
        params.put("clientSecret", MD5Util.toMD5String(UUIDUtil.getUUID()));
        params.put("clientId", clientId);
        if (token != null) {
            setSaveInfo(token, params);
        } else {
            setSaveInfo(params);
        }
        clientDao.saveClient(params);
        return clientId;
    }

    @Override
    public SuccessResult removeClient(String ids) throws RemoveException {
        removeClientInfo(null, ids);
        return new SuccessResult();
    }

    @Override
    public SuccessResult removeClientByToken(String token, String ids) throws RemoveException {
        removeClientInfo(token, ids);
        return new SuccessResult();
    }

    /**
     * 删除客户端
     *
     * @param token
     * @param ids
     */
    private void removeClientInfo(String token, String ids) {
        Map<String, Object> params = getHashMap(3);
        params.put("clientIds", Arrays.asList(ids.split("_")));
        if (token != null) {
            setUpdateInfo(token, params);
        } else {
            setUpdateInfo(params);
        }
        clientDao.removeClient(params);
    }

    @Override
    public void deleteClient(String ids) throws RemoveException {
        Map<String, Object> params = getHashMap(3);
        params.put("clientIds", Arrays.asList(ids.split("_")));
        clientDao.deleteClient(params);
    }

    @Override
    public SuccessResult updateClient(String clientId, ClientVO clientVO) throws Exception {
        updateClientInfo(null, clientId, clientVO);
        return new SuccessResult();
    }

    @Override
    public SuccessResult updateClientByToken(String token, String clientId, ClientVO clientVO) throws Exception {
        updateClientInfo(token, clientId, clientVO);
        return new SuccessResult();
    }

    @Override
    public SuccessResult updateClientLicense(String clientId, ClientLicenseAuthorizationDTO clientLicenseAuthorizationDTO) throws Exception {
        DateTime startDateTime = DateTime.parse(clientLicenseAuthorizationDTO.getLicenseStartTime(), DateTimeFormat.forPattern(ISystemConstant.DATE_FORMATTER_YYYY_MM_DD));
        DateTime expireDateTime = startDateTime.plusDays(clientLicenseAuthorizationDTO.getLicenseEffectiveDays());
        clientLicenseAuthorizationDTO.setLicenseExpirationDate(expireDateTime.toString(ISystemConstant.DATE_FORMATTER_YYYY_MM_DD));
        Map<String, Object> params = HashMapUtil.beanToMap(clientLicenseAuthorizationDTO);
        params.put("clientId", clientId);
        setUpdateInfo(params);
        clientDao.updateClientLicense(params);
        return new SuccessResult();
    }

    /**
     * 修改客户端
     *
     * @param token
     * @param clientId
     * @param clientVO
     */
    private void updateClientInfo(String token, String clientId, ClientVO clientVO) throws Exception {
        Map<String, Object> params = HashMapUtil.beanToMap(clientVO);
        params.put("clientId", clientId);
        if (token != null) {
            setUpdateInfo(token, params);
        } else {
            setUpdateInfo(params);
        }
        clientDao.updateClient(params);
    }

    @Override
    public ClientDTO getClientById(String clientId) throws SearchException {
        Map<String, Object> params = super.getHashMap(1);
        params.put("clientId", clientId);
        return clientDao.getClient(params);
    }

    @Override
    public List<ClientDTO> listClient(Map<String, Object> params) throws SearchException {
        return clientDao.listClient(params);
    }

    @Override
    public SuccessResultList<List<ClientDTO>> listPageClient(ListPage page) throws SearchException {
        PageHelper.startPage(page.getPage(), page.getRows());
        List<ClientDTO> clientDTOs = clientDao.listClient(page.getParams());
        // 在线，离线状态
        SocketServerManager socketServerManager = SocketServerManager.getInstance();
        for (ClientDTO clientDTO : clientDTOs) {
            SocketClientBO socketClientBO = socketServerManager.getOnlineClientByClientId(clientDTO.getClientId());
            if (socketClientBO != null) {
                // 在线状态
                clientDTO.setOnlineStatus(1);
                clientDTO.setLastOnlineTime(new DateTime(socketClientBO.getLastTime()).toString(ISystemConstant.DATE_FORMATTER_YYYY_MM_DD_HH_MM_SS));
                continue;
            }
            socketClientBO = socketServerManager.getOfflineClientByClientId(clientDTO.getClientId());
            if (socketClientBO != null) {
                // 离线状态
                clientDTO.setOnlineStatus(0);
                clientDTO.setLastOnlineTime(new DateTime(socketClientBO.getLastTime()).toString(ISystemConstant.DATE_FORMATTER_YYYY_MM_DD_HH_MM_SS));
                continue;
            }
            // 未连接
            clientDTO.setOnlineStatus(-1);
        }
        PageInfo<ClientDTO> pageInfo = new PageInfo<>(clientDTOs);
        return new SuccessResultList<>(clientDTOs, pageInfo.getPageNum(), pageInfo.getTotal());
    }

    @Override
    public Integer countNumberClient(Map<String, Object> params) throws SearchException {
        Integer count = clientDao.countClient(params);
        return count == null ? 0 : count;
    }

    @Override
    public SuccessResultData<Integer> countClient(Map<String, Object> params) throws SearchException {
        return new SuccessResultData<>(countNumberClient(params));
    }

    @Override
    public SuccessResultData<String> getClientSecretByClientId(String clientId) throws Exception {
        String clientSecret = clientDao.getClientSecretByClientId(clientId);
        if (StringUtils.isBlank(clientSecret)) {
            return new SuccessResultData<>("");
        }
        return new SuccessResultData<>(AesUtil.aesCommonEncoder(CLIENT_SECRET_ENCODE_KEY, clientDao.getClientSecretByClientId(clientId)));
    }

    @Override
    public ClientLicenseAuthorizationDTO getClientLicenseAuthorizationByClientId(String clientId) throws SearchException {
        return clientDao.getClientLicenseAuthorizationByClientId(clientId);
    }

    @Override
    public SuccessResultData<String> getClientLicenseByClientId(String clientId) throws SearchException {
        return new SuccessResultData<>(getClientLicense(clientId));
    }

    @Override
    public String getClientLicense(String clientId) throws SearchException {
        ClientLicenseAuthorizationDTO clientLicenseAuthorizationDTO = clientDao.getClientLicenseAuthorizationByClientId(clientId);
        if (clientLicenseAuthorizationDTO == null) {
            return "暂无";
        }
        if (StringUtils.isBlank(clientLicenseAuthorizationDTO.getLicenseStartTime())) {
            return "暂无";
        }
        if (clientLicenseAuthorizationDTO.getLicenseEffectiveDays() == null || clientLicenseAuthorizationDTO.getLicenseEffectiveDays() <= 0) {
            clientLicenseAuthorizationDTO.setLicenseEffectiveDays(0);
        }
        return License.getLicense(clientLicenseAuthorizationDTO.getLicenseStartTime(), clientLicenseAuthorizationDTO.getLicenseEffectiveDays().toString(), clientLicenseAuthorizationDTO.getMacAddress(), CLIENT_LICENSE_KEY);
    }

    @Override
    public ClientBO getClientBOByClientId(String clientId) throws SearchException {
        Map<String, Object> params = getHashMap(2);
        params.put("clientId", clientId);
        return clientDao.getClientBO(params);
    }

    @Override
    public SuccessResultData<Map<String, Object>> getClientInfoByClientId(String clientId) throws SearchException {
        SocketClientBO socketClientBO = SocketServerManager.getInstance().getOnlineClientByClientId(clientId);
        if (socketClientBO == null) {
            throw new SearchException("该系统不在线");
        }
        Map<String, Object> result = getHashMap(10);
        result.put("system", socketClientBO.getSystemInfo());
        result.put("diskList", socketClientBO.getDiskList());
        result.put("memoryQueue", socketClientBO.getMemoryQueue());
        result.put("jvmQueue", socketClientBO.getJvmQueue());
        result.put("cpuQueue", socketClientBO.getCpuQueue());
        return new SuccessResultData<>(result);
    }

}