package cn.com.ty.lift.push.app;

import cn.com.ty.lift.common.model.PushMessage;
import cn.com.ty.lift.common.model.TimeMessage;
import cn.com.ty.lift.common.utils.ValuePool;
import cn.com.ty.lift.push.message.service.TimeMessageService;
import cn.com.ty.lift.push.message.service.UserAccountService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 消息推送消费者，监听队列，从队列中取出message执行推送, queue >>> device platform
 *
 * @author wcz
 * @since 2020/4/26
 */
@Slf4j
@Component
@AllArgsConstructor
public class PushConsumer {

    private XingePush xingePush;
    private JmsMessagingTemplate jmsMessagingTemplate;
    private TimeMessageService TimeMessageService;
    private RedisTemplate redisTemplate;
    private final UserAccountService userAccountService;
    private final TimeMessageService timeMessageService;

    private class Processor {
        private String destination;
        private PushMessage pushMessage;
        private boolean result;

        private Processor(String destination, PushMessage pushMessage) {
            this.destination = destination;
            this.pushMessage = pushMessage;
        }

        private Processor perform() {
            String title = pushMessage.getTitle();
            String content = pushMessage.getContent();
            List<String> toList = pushMessage.getToList();
            switch (this.destination) {
                case ValuePool.PUSH_QUEUE_ANDROID_TOKEN:
                    result = xingePush.pushTokenOnAndroid(title, content, toList);
                    break;
                case ValuePool.PUSH_QUEUE_ANDROID_ALL:
                    result = xingePush.pushAllOnAndroid(title, content);
                    break;
                case ValuePool.PUSH_QUEUE_IOS_TOKEN:
                    result = xingePush.pushTokenOnIos(title, content, toList);
                    break;
                case ValuePool.PUSH_QUEUE_IOS_ALL:
                    result = xingePush.pushAllOnIos(title, content);
                    break;
                default:
                    result = true;
            }
            return this;
        }

        private void tryAgain() {
            int tryCount = pushMessage.getTryCount();
            if (!result && tryCount < ValuePool.PUSH_TRY_MAX_TIMES) {
                pushMessage.setTryCount(tryCount + 1);
                jmsMessagingTemplate.send(destination, new GenericMessage<>(pushMessage));
            }
        }
    }

    private void process(String destination, PushMessage pushMessage) {
        if (pushMessage.needSplit()) {
            List<ArrayList<String>> doSplit = pushMessage.doSplit(ValuePool.PUSH_MAX_SIZE);
            for (ArrayList<String> list : doSplit) {
                pushMessage.setToList(list);
                new Processor(destination, pushMessage).perform().tryAgain();
            }
        } else {
            new Processor(destination, pushMessage).perform().tryAgain();
        }
    }

    @JmsListener(destination = ValuePool.PUSH_QUEUE_ANDROID_TOKEN)
    public void listenAndroidTokenQueue(PushMessage pushMessage) {
        saveMessage(pushMessage);

        log.info("listen {} receive message：{}", ValuePool.PUSH_QUEUE_ANDROID_TOKEN, pushMessage);
        process(ValuePool.PUSH_QUEUE_ANDROID_TOKEN, pushMessage);
    }

    @JmsListener(destination = ValuePool.PUSH_QUEUE_ANDROID_ALL)
    public void listenAndroidAllQueue(PushMessage pushMessage) {
        saveMessage(pushMessage);

        log.info("listen {} receive message：{}", ValuePool.PUSH_QUEUE_ANDROID_ALL, pushMessage);
        process(ValuePool.PUSH_QUEUE_ANDROID_ALL, pushMessage);
    }

    @JmsListener(destination = ValuePool.PUSH_QUEUE_IOS_TOKEN)
    public void listenIosTokenQueue(PushMessage pushMessage) {
        saveMessage(pushMessage);

        log.info("listen {} receive message：{}", ValuePool.PUSH_QUEUE_IOS_TOKEN, pushMessage);
        process(ValuePool.PUSH_QUEUE_IOS_TOKEN, pushMessage);
    }

    @JmsListener(destination = ValuePool.PUSH_QUEUE_IOS_ALL)
    public void listenIosAllQueue(PushMessage pushMessage) {
        saveMessage(pushMessage);

        log.info("listen {} receive message：{}", ValuePool.PUSH_QUEUE_IOS_ALL, pushMessage);
        process(ValuePool.PUSH_QUEUE_IOS_ALL, pushMessage);
    }

    /**
     * 将推送消息存储到数据库
     *
     * @param pushMessage 要推送的消息
     */
    private void saveMessage(PushMessage pushMessage) {
        List<TimeMessage> timeMessages = new ArrayList<>();
        pushMessage.getUsers().forEach((k, v) -> {
            TimeMessage timeMessage = new TimeMessage();
            timeMessage.setUserId(k);
            timeMessage.setContent(pushMessage.getContent());
            switch (pushMessage.getTitle()) {
                case "公司公告":
                case "团队消息":
                    timeMessage.setType(1);
                    break;
                case "保养消息":
                    timeMessage.setType(2);
                    break;
                case "急修消息":
                    timeMessage.setType(3);
                    break;
                case "提醒":
                case "工作消息":
                    timeMessage.setType(4);
                    break;
            }
            timeMessage.setDeviceModel(v);
            timeMessage.setCreateUserId(10000L);
            timeMessage.setCreateTime(LocalDateTime.now());
            timeMessages.add(timeMessage);
        });
        log.info("消息记录列表:" + timeMessages.toString());
        if (!timeMessages.isEmpty()) {
            log.info("消息不为空，保存消息到消息中心");
            timeMessageService.saveBatch(timeMessages);
        }
    }
}