package cn.com.ty.lift.common.model;

import cn.com.ty.lift.common.utils.ValuePool;
import cn.hutool.core.collection.IterUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.messaging.support.GenericMessage;

import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 推送消息
 *
 * @author wcz
 * @since 2020/4/14
 */
@Slf4j
@Data
public class PushMessage implements Serializable {

    private static final long serialVersionUID = 4125096758372084309L;

    private String title;
    private String content;
    private Hashtable<Long, Integer> users = new Hashtable<>();
    private List<String> toList = new ArrayList<>();
    //the count of try again. Increase 1 for each failure, maximum times 100
    private int tryCount = 0;

    private PushMessage() {
    }

    private PushMessage(String title, String content) {
        this.title = title;
        this.content = content;
    }

    public PushMessage add(String to) {
        this.toList.add(to);
        return this;
    }

    private static PushMessage create(String title, String content) {
        return new PushMessage(title, content);
    }

    private static PushMessage team(String content) {
        return create("团队消息", content);
    }

    private static PushMessage work(String content) {
        return create("工作消息", content);
    }

    private static PushMessage maintain(String content) {
        return create("保养消息", content);
    }

    private static PushMessage emergency(String content) {
        return create("急修消息", content);
    }

    private static PushMessage manager(String content) {
        return create("提醒", content);
    }

    private static PushMessage inspection(String content) {
        return create("年检消息", content);
    }

    /**
     * PC
     * 所有文员
     * 申请团队
     * 【申请人】申请加入【团队名称】。
     */
    public static PushMessage teamApply(String applyName, String teamName) {
        String message = "%s申请加入%s。";
        String content = String.format(message, applyName, teamName);
        return team(content);
    }

    /**
     * 移动端
     * 区域主管、申请人
     * 加入团队成功
     * 【申请人】已经成功加入【团队名称】。
     */
    public static PushMessage teamJoin(String applyName, String teamName) {
        String message = "%s已经成功加入%s。";
        String content = String.format(message, applyName, teamName);
        return team(content);
    }

    /**
     * 移动端
     * 区域主管、被踢人
     * 移出团队
     * 【被踢人】已经被移出【团队名称】
     */
    public static PushMessage teamKickOut(String kickName, String teamName) {
        String message = "%s已经被踢出%s。";
        String content = String.format(message, kickName, teamName);
        return team(content);
    }

    /**
     * PC/移动端
     * 区域主管（项目所属）、所有文员
     * 物业申请项目
     * 物业【申请人】申请【项目名称】【评价/查看】权限。
     */
    public static PushMessage workApplyPermission(String applyName, String projectName, String permission) {
        String message = "物业%s申请%s的%s权限。";
        String content = String.format(message, applyName, projectName, permission);
        return work(content);
    }

    /**
     * 移动端
     * 区域主管（项目所属）
     * 物业获得权限
     * 物业【申请人】成功获得【项目名称】【评价/查看】权限。
     */
    public static PushMessage workObtainPermission(String applyName, String projectName, String permission) {
        String message = "物业%s成功获得%s的%s权限。";
        String content = String.format(message, applyName, projectName, permission);
        return work(content);
    }

    /**
     * 移动端
     * 区域主管（项目所属）
     * 取消物业权限
     * 物业【申请人】失去【项目名称】【评价/查看】权限。
     */
    public static PushMessage workAbolishPermission(String applyName, String projectName, String permission) {
        String message = "物业%s失去%s的%s权限。";
        String content = String.format(message, applyName, projectName, permission);
        return work(content);
    }

    /**
     * PC/移动端
     * 超管、区域主管（项目所属）、所有文员（项目所属）
     * 新增项目
     * 【区域名称】新增【项目名称】项目，共计【台量】台，生效时间【生效时间】，区域主管【区域主管】。
     */
    public static PushMessage workAddProject(String areaName, String projectName, int num, String startDate, String directorName) {
        String message = "%s新增%s项目，共计%s台，生效时间%s，区域主管%s。";
        String content = String.format(message, areaName, projectName, num, startDate, directorName);
        return work(content);
    }

    /**
     * PC/移动端
     * 超管、区域主管（项目所属）、所有文员（项目所属）
     * 项目开始生效
     * 【区域名称】【项目名称】项目进入服务期。
     */
    public static PushMessage workStartProject(String areaName, String projectName) {
        String message = "%s的%s项目进入服务期。";
        String content = String.format(message, areaName, projectName);
        return work(content);
    }

    /**
     * PC/移动端
     * 超管、区域主管（项目所属）、所有文员（项目所属）
     * 项目逾期
     * 【区域名称】【项目名称】已经逾期，请尽快办理合同续签或停止服务手续。
     */
    public static PushMessage workProjectOverdue(String areaName, String projectName) {
        String message = "%s的%s已经逾期，请尽快办理合同续签或停止服务手续。";
        String content = String.format(message, areaName, projectName);
        return work(content);
    }

    /**
     * PC/移动端
     * 超管、区域主管（项目所属）、所有文员（项目所属）
     * 停止服务
     * 【区域名称】【项目名称】已经停止服务，共计【台量】台。
     */
    public static PushMessage workProjectStopService(String areaName, String projectName, int num) {
        String message = "%s的%s已经停止服务，共计%s台。";
        String content = String.format(message, areaName, projectName, num);
        return work(content);
    }

    /**
     * PC/移动端
     * 超管、区域主管（项目所属）、所有文员（项目所属）
     * 恢复逾期
     * 【区域名称】【项目名称】已经续签完毕。
     */
    public static PushMessage workProjectRecoverService(String areaName, String projectName) {
        String message = "%s的%s已经续签完毕。";
        String content = String.format(message, areaName, projectName);
        return work(content);
    }

    /**
     * PC/移动端
     * 超管、区域主管（项目所属）、所有文员（项目所属）
     * 区域更换负责人
     * 【区域名称】的负责人，由【原区域主管】变更为【新区域主管】
     */
    public static PushMessage workReplaceRegionCharger(String areaName, String original, String newer) {
        String message = "%s的负责人，由%s变更为%s";
        String content = String.format(message, areaName, original, newer);
        return work(content);
    }

    /**
     * PC/移动端
     * 超管、区域主管（项目所属）、所有文员（项目所属）
     * 创建电梯
     * 【创建人】为【项目名称】新增电梯位于【电梯位置】，注册代码【注册代码】
     */
    public static PushMessage workCreateLift(String operator, String projectName, String devicePosition, String registrationCode) {
        String message = "%s为%s新增电梯位于%s，注册代码%s";
        String content = String.format(message, operator, projectName, devicePosition, registrationCode);
        return work(content);
    }

    /**
     * PC/移动端
     * 超管、区域主管（项目所属）、所有文员（项目所属）
     * 更新电梯信息（除定位、更换负责人）
     * 【更新人】更新【项目名称】【电梯位置】的电梯信息，注册代码【注册代码】
     */
    public static PushMessage workModifyLift(String operator, String projectName, String devicePosition, String registrationCode) {
        String message = "%s更新%s的%s的电梯信息，注册代码%s";
        String content = String.format(message, operator, projectName, devicePosition, registrationCode);
        return work(content);
    }

    /**
     * PC/移动端
     * 超管、区域主管（项目所属）、所有文员（项目所属）
     * 更新电梯定位
     * 【更新人】更新【项目名称】【电梯位置】的电梯定位为【电梯位置新】，注册代码【注册代码】
     */
    public static PushMessage workModifyLiftPosition(String operator, String projectName, String devicePosition, String newPosition, String registrationCode) {
        String message = "%s更新%s的%s的电梯定位为%s，注册代码%s";
        String content = String.format(message, operator, projectName, devicePosition, newPosition, registrationCode);
        return work(content);
    }

    /**
     * PC/移动端
     * 超管、区域主管（项目所属）、所有文员（项目所属）、相关维保工
     * 电梯更换主要负责人
     * 【区域名称】的【项目名称】的【电梯位置】电梯，【注册代码】，主要负责人由【原负责人】更换为【新负责人】。
     */
    public static PushMessage workReplaceLiftCharger(String areaName, String projectName, String devicePosition, String registrationCode, String original, String newer) {
        String message = "%s的%s的%s电梯，注册代码%s，主要负责人由%s更换为%s。";
        String content = String.format(message, areaName, projectName, devicePosition, registrationCode, original, newer);
        return work(content);
    }

    //保养类型 1.半月，2.季度，3.半年，4.全年
    private static String getMaintainType(int type) {
        switch (type) {
            case 1:
                return "半月保";
            case 2:
                return "季度保";
            case 3:
                return "半年保";
            case 4:
                return "全年保";
            default:
                return "未知类型";
        }
    }

    /**
     * 移动端
     * 区域主管、相关维保工
     * 制定保养计划
     * 维保计划制定：【区域名称】【项目名称】的【电梯位置】电梯，【注册代码】，保养间隔时间【x】天，下次保养时间【下次保养时间】，保养类型【保养类型】，负责人【电梯负责人】。制定人【操作人】
     * 保养类型 1.半月，2.季度，3.半年，4.全年
     */
    public static PushMessage maintainCreatePlan(String areaName, String projectName, String devicePosition, String registrationCode, int interval, LocalDate planDate, int type, String liftCharge, String operator) {
        String message = "维保计划制定：%s%s的%s电梯，%s，保养间隔时间%s天，下次保养时间%tF，保养类型%s，负责人%s。制定人%s";
        String content = String.format(message, areaName, projectName, devicePosition, registrationCode, interval, planDate, getMaintainType(type), liftCharge, operator);
        return maintain(content);
    }

    /**
     * 移动端
     * 区域主管、相关维保工
     * 修改保养计划
     * 维保计划修改：【区域名称】【项目名称】的【电梯位置】电梯，【注册代码】，保养间隔时间【x】天，下次保养时间【下次保养时间】，保养类型【保养类型】，负责人【电梯负责人】。修改人【操作人】
     */
    public static PushMessage maintainModifyPlan(String areaName, String projectName, String devicePosition, String registrationCode, int interval, LocalDate planDate, int type, String liftCharge, String operator) {
        String message = "维保计划修改：%s%s的%s电梯，%s，保养间隔时间%s天，下次保养时间%tF，保养类型%s，负责人%s。修改人%s";
        String content = String.format(message, areaName, projectName, devicePosition, registrationCode, interval, planDate, getMaintainType(type), liftCharge, operator);
        return maintain(content);
    }

    /**
     * 移动端
     * 相关维保工
     * 每天有维保任务
     * 您今天有需要保养的电梯【x】台，请查看任务!
     */
    public static PushMessage maintainHasTaskDaily(int num) {
        String message = "您今天有需要保养的电梯%s台，请查看任务!";
        String content = String.format(message, num);
        return maintain(content);
    }

    private static String getTrappedDesc(int isTrapped) {
        return isTrapped == 1 ? "已" : "未";
    }

    /**
     * 移动端
     * 总经理、区域主管（项目所属）、相关维保工
     * 急修指派
     * 【区域名称】的【项目名称】的【电梯位置】电梯，注册代码【注册代码】，于【报修时间】接到召修信息，【已/未】困人，请【被派单人】立即响应。
     */
    public static PushMessage emergencyAssign(String areaName, String projectName, String devicePosition, String registrationCode, LocalDateTime callerDate, int isTrapped, String callerFaultDescription, String workerName) {
        String message = "%s的%s的%s电梯，注册代码%s，于%tF %tT接到召修信息，%s困人，召修描述：%s，请%s立即响应。";
        String content = String.format(message, areaName, projectName, devicePosition, registrationCode, callerDate, callerDate, getTrappedDesc(isTrapped), callerFaultDescription, workerName);
        return emergency(content);
    }

    /**
     * PC/移动端
     * 总经理、区域主管（项目所属）、所有文员（项目所属）、相关维保工
     * 物业发起急修
     * 【区域名称】的【项目名称】的【电梯位置】电梯，注册代码【注册代码】，物业端于【报修时间】发出召修信息，【已/未】困人，请【电梯主要负责人】立即响应。
     */
    public static PushMessage emergencyAssignByProperty(String areaName, String projectName, String devicePosition, String registrationCode, LocalDateTime callerDate, int isTrapped, String callerFaultDescription, String workerName) {
        String message = "%s的%s的%s电梯，注册代码%s，物业端于%tF %tT发出召修信息，%s困人，召修描述：%s，请%s立即响应。";
        String content = String.format(message, areaName, projectName, devicePosition, registrationCode, callerDate, callerDate, getTrappedDesc(isTrapped), callerFaultDescription, workerName);
        return emergency(content);
    }

    /**
     * 移动端
     * 总经理、区域主管（项目所属）、相关维保工
     * 转派
     * 【区域名称】的【项目名称】的【电梯位置】电梯，注册代码【注册代码】，物业端于【报修时间】发出召修信息，【已/未】困人，请【被派单人】立即响应。
     * 【原被派单人】：【区域名称】的【项目名称】的【电梯位置】电梯，注册代码【注册代码】，急修信息已经转派给【被派单人】。
     */
    public static PushMessage emergencyTransfer(String areaName, String projectName, String devicePosition, String registrationCode, LocalDateTime callerDate, int isTrapped, String callerFaultDescription, String workerName) {
        String message = "%s的%s的%s电梯，注册代码%s，物业端于%tF %tT发出召修信息，%s困人，召修描述：%s，请%s立即响应。";
        String content = String.format(message, areaName, projectName, devicePosition, registrationCode, callerDate, callerDate, getTrappedDesc(isTrapped), callerFaultDescription, workerName);
        return emergency(content);
    }

    /**
     * 移动端
     * 【原被派单人】收到消息：【区域名称】的【项目名称】的【电梯位置】电梯，注册代码【注册代码】，急修信息已经转派给【被派单人】。
     */
    public static PushMessage emergencyTransferForOriginal(String areaName, String projectName, String devicePosition, String registrationCode, String workerName) {
        String message = "%s的%s的%s电梯，注册代码%s，急修信息已经转派给%s。";
        String content = String.format(message, areaName, projectName, devicePosition, registrationCode, workerName);
        return emergency(content);
    }

    /**
     * PC/移动端
     * 总经理、区域主管（项目所属）、所有文员（项目所属）
     * 维保工接收急修通知
     * 【区域名称】的【项目名称】的【电梯位置】电梯，注册代码【注册代码】，于【报修时间】接到召修信息，维保工已确认。
     */
    public static PushMessage emergencyTaking(String areaName, String projectName, String devicePosition, String registrationCode, LocalDateTime callerDate) {
        String message = "%s的%s的%s电梯，注册代码%s，于%tF %tT接到召修信息，维保工已接收通知。";
        String content = String.format(message, areaName, projectName, devicePosition, registrationCode, callerDate, callerDate);
        return emergency(content);
    }

    /**
     * PC/移动端
     * 总经理、区域主管（项目所属）、所有文员（项目所属）
     * 维保工到达现场
     * 【区域名称】的【项目名称】的【电梯位置】电梯，注册代码【注册代码】，于【报修时间】接到召修信息，维保工已于【到达时间】到达现场。
     */
    public static PushMessage emergencyArrive(String areaName, String projectName, String devicePosition, String registrationCode, LocalDateTime callerDate, LocalDateTime arriveTime) {
        String message = "%s的%s的%s电梯，注册代码%s，于%tF %tT接到召修信息，维保工已于%tF %tT到达现场。";
        String content = String.format(message, areaName, projectName, devicePosition, registrationCode, callerDate, callerDate, arriveTime, arriveTime);
        return emergency(content);
    }

    /**
     * PC/移动端
     * 总经理、区域主管（项目所属）、所有文员（项目所属）
     * 维保工提交急修单
     * 【区域名称】的【项目名称】的【电梯位置】电梯，注册代码【注册代码】，于【报修时间】接到召修信息，电梯已于【恢复时间】恢复正常。
     */
    public static PushMessage emergencyOrder(String areaName, String projectName, String devicePosition, String registrationCode, LocalDateTime callerDate, LocalDateTime recoveryDate) {
        String message = "%s的%s的%s电梯，注册代码%s，于%tF %tT接到召修信息，电梯已于%tF %tT恢复正常。";
        String content = String.format(message, areaName, projectName, devicePosition, registrationCode, callerDate, callerDate, recoveryDate, recoveryDate);
        return emergency(content);
    }

    /**
     * PC/移动端
     * 所有人
     * 公司发送公告
     * 有一条公司公告，请查收
     */
    public static PushMessage announcementNotice(String content) {
        return create("公司公告", content);
    }

    /**
     * PC
     * 所有文员
     * 早上8点
     * 即时提醒：今天计划有X台电梯需保养，X台电梯正在维修中。
     */
    public static PushMessage managerMaintainDaily(int maintain, int repair) {
        String message = "即时提醒：今天计划有%s台电梯需保养，%s台电梯正在维修中。";
        String content = String.format(message, maintain, repair);
        return manager(content);
    }

    /**
     * 移动端
     * 区域主管（项目所属）
     * 下午4点
     * 即时提醒：【区域名称】今天共发生急修X次，已维修完毕X次，X次仍在处理中；X台电梯计划保养未完成。
     */
    public static PushMessage managerTaskForRegionChargerDaily(String areaName, int total, int finish, int doings, int todos) {
        String message = "即时提醒：%s今天共发生急修%s次，已维修完毕%s次，%s次仍在处理中；%s台电梯计划保养未完成。";
        String content = String.format(message, areaName, total, finish, doings, todos);
        return manager(content);
    }

    /**
     * 移动端
     * 总经理
     * 下午4点
     * 即时提醒：今天共发生急修X次，已维修完毕X次，X次仍在处理中；X台电梯计划保养未完成。
     */
    public static PushMessage managerTaskForLeaderDaily(int total, int finish, int doings, int todos) {
        String message = "即时提醒：今天共发生急修%s次，已维修完毕%s次，%s次仍在处理中；%s台电梯计划保养未完成。";
        String content = String.format(message, total, finish, doings, todos);
        return manager(content);
    }


    /**
     * 移动端
     * 总经理，区域主管（项目所属）
     * 晚上8点
     * 日报：截止目前，今天应保养X台，已完成X台，X台即将超期；今天共发起急修X起，已处理完成X起，X起正在处理中。
     */
    public static PushMessage managerReportDaily(int needs, int finish, int overdue, int totalRepair, int finishRepair, int doingRepair) {
        String message = "日报：截止目前，今天应保养%s台，已完成%s台，%s台即将超期；今天共发起急修%s起，已处理完成%s起，%s起正在处理中。";
        String content = String.format(message, needs, finish, overdue, totalRepair, finishRepair, doingRepair);
        return manager(content);
    }

    /**
     * PC/移动端
     * 区域主管（项目所属），文员（所属文员），电梯主要负责人
     * 年检到期前45天
     * 【项目名称】的【电梯位置】电梯，注册代码【注册代码】，将于45日后年检到期。
     */
    public static PushMessage inspectionAdvance45daysNotice(String projectName, String devicePosition, String registrationCode) {
        String message = "%s的%s电梯，注册代码%s，将于45日后年检到期。";
        String content = String.format(message, projectName, devicePosition, registrationCode);
        return inspection(content);
    }

    /**
     * PC/移动端
     * 区域主管（项目所属），文员（所属文员），电梯主要负责人
     * 年检到期前15天
     * 【项目名称】的【电梯位置】电梯，注册代码【注册代码】，仍未启动年检，将于15日后年检到期。
     */
    public static PushMessage inspectionAdvance15daysNotice(String projectName, String devicePosition, String registrationCode) {
        String message = "%s的%s电梯，注册代码%s，仍未启动年检，将于15日后年检到期。";
        String content = String.format(message, projectName, devicePosition, registrationCode);
        return inspection(content);
    }

    /**
     * PC/移动端
     * 区域主管（项目所属），电梯负责人
     * 确认现场检验时间
     * 【项目名称】的【电梯位置】电梯，注册代码【注册代码】，已确认现场检验时间为【现场检验时间】。
     */
    public static PushMessage inspectionConfirmCheckDate(String projectName, String devicePosition, String registrationCode, LocalDate checkDate) {
        String message = "%s的%s电梯，注册代码%s，已确认现场检验时间为%tF。";
        String content = String.format(message, projectName, devicePosition, registrationCode, checkDate);
        return inspection(content);
    }

    /**
     * 移动端
     * 所有人
     * 【新闻标题】
     */
    public static PushMessage newsNotice(String title) {
        return create("发布新闻", title);
    }

    /**
     * 检查推送列表总数是否需要拆分，信鸽推送一次最多1000
     */
    public boolean needSplit() {
        return Objects.nonNull(toList) && toList.size() > ValuePool.PUSH_MAX_SIZE;
    }

    /**
     * 拆分推送设备列表
     */
    public List<ArrayList<String>> doSplit(final int length) {
        List<ArrayList<String>> splits = new ArrayList<>();
        int size = toList.size();
        log.info("the size of toList is {}, need to split.", size);
        //0 1000 2000
        for (int i = 0; i < size; i += length) {
            if (i + length > size) {
                splits.add(new ArrayList<>(toList.subList(i, size)));
            } else {
                splits.add(new ArrayList<>(toList.subList(i, i + length)));
            }
        }
        log.info("the size of splits : {}", splits.size());
        return splits;
    }

    /**
     * 同时推送到多个设备token
     */
    public boolean sendTokenOnPlatform(JmsMessagingTemplate jmsMessagingTemplate, List<PushUserInfo> pushUserInfos) {
        try {
            if (IterUtil.isEmpty(pushUserInfos)) {
                return false;
            }
            Set<String> toAndroid = new HashSet<>();
            Set<String> toIos = new HashSet<>();
            for (PushUserInfo pushUserInfo : pushUserInfos) {
                if (pushUserInfo.available()) {
                    if (pushUserInfo.isAndroid()) {
                        toAndroid.add(pushUserInfo.getDeviceFlag());
                    } else if (pushUserInfo.isIos()) {
                        toIos.add(pushUserInfo.getDeviceFlag());
                    }
                }
            }
            resetUsers(pushUserInfos);
            if (IterUtil.isNotEmpty(toAndroid)) {
                this.setToList(new ArrayList<>(toAndroid));
                jmsMessagingTemplate.send(ValuePool.PUSH_QUEUE_ANDROID_TOKEN, new GenericMessage<>(this));
            } else if (IterUtil.isNotEmpty(toIos)) {
                this.setToList(new ArrayList<>(toIos));
                jmsMessagingTemplate.send(ValuePool.PUSH_QUEUE_IOS_TOKEN, new GenericMessage<>(this));
            } else {
                return false;
            }
            return true;
        } catch (Exception e) {
            log.error("Failed to Send pushMessage to ANDROID & IOS TOKEN Message Queue: ", e);
            return false;
        }
    }

    /**
     * 推送到单个设备
     */
    public boolean sendTokenOnPlatform(JmsMessagingTemplate jmsMessagingTemplate, PushUserInfo pushUserInfo) {
        try {
            if (Objects.isNull(pushUserInfo)) {
                return false;
            }
            if (!pushUserInfo.available()) {
                return false;
            }
            resetUsers(pushUserInfo);
            this.add(pushUserInfo.getDeviceFlag());
            if (pushUserInfo.isAndroid()) {
                jmsMessagingTemplate.send(ValuePool.PUSH_QUEUE_ANDROID_TOKEN, new GenericMessage<>(this));
            } else if (pushUserInfo.isIos()) {
                jmsMessagingTemplate.send(ValuePool.PUSH_QUEUE_IOS_TOKEN, new GenericMessage<>(this));
            } else {
                return false;
            }
            return true;
        } catch (Exception e) {
            log.error("Failed to Send pushMessage to ANDROID & IOS TOKEN Message Queue: ", e);
            return false;
        }
    }

    /**
     * 同时推送android和ios全平台
     */
    public boolean sendAllOnPlatform(JmsMessagingTemplate jmsMessagingTemplate) {
        users.clear();
        try {
            jmsMessagingTemplate.send(ValuePool.PUSH_QUEUE_ANDROID_ALL, new GenericMessage<>(this));
            jmsMessagingTemplate.send(ValuePool.PUSH_QUEUE_IOS_ALL, new GenericMessage<>(this));
            return true;
        } catch (Exception e) {
            log.error("Failed to Send pushMessage to ANDROID & IOS ALL Message Queue: ", e);
            return false;
        }
    }

    /**
     * 将用户id和设备类型传到消息中间件中，方便消息中心功能来保存
     *
     * @param pushUserInfos 用户信息列表
     */
    private void resetUsers(List<PushUserInfo> pushUserInfos) {
        users.clear();
        pushUserInfos.forEach(pushUserInfo -> {
                    if (pushUserInfo.getDeviceModel() != null) {
                        users.put(pushUserInfo.getUserId(), pushUserInfo.getDeviceModel());
                    }
                }
        );
    }

    /**
     * 将用户id和设备类型传到消息中间件中，方便消息中心功能来保存
     *
     * @param pushUserInfo 用户信息列表
     */
    private void resetUsers(PushUserInfo pushUserInfo) {
        users.clear();
        users.put(pushUserInfo.getUserId(), pushUserInfo.getDeviceModel());
    }
}
