package com.zhujizheng.IHome.everymoment.service;

import com.zhujizheng.IHome.everymoment.dto.*;
import com.zhujizheng.IHome.everymoment.sysmsg.PYEveryMomentCommentSysMsg;
import com.zhujizheng.IHome.everymoment.sysmsg.PYEveryMomentSysMsg;
import com.zhujizheng.IHome.everymoment.sysmsg.PYEveryMomentThumbupSysMsg;
import com.zhujizheng.IHome.everymoment.vo.PYEveryMomentCommentVO;
import com.zhujizheng.IHome.everymoment.vo.PYEveryMomentImgVO;
import com.zhujizheng.IHome.everymoment.vo.PYEveryMomentThumbupVO;
import com.zhujizheng.IHome.generator.dao.*;
import com.zhujizheng.IHome.generator.mapper.*;
import com.zhujizheng.IHome.everymoment.vo.PYEveryMomentVO;
import com.zhujizheng.IHome.everymomentmsg.vo.PYEveryMomentMsgVO;
import com.zhujizheng.IHome.util.CodeUtil;
import com.zhujizheng.IHome.util.aes.AESUtil;
import com.zhujizheng.IHome.util.alipush.AliPushService;
import com.zhujizheng.IHome.util.dto.DTOUtils;
import com.zhujizheng.IHome.everymomentmsg.net.NetEveryMomentMsg;
import com.zhujizheng.IHome.websocket.server.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Created with IntelliJ IDEA
 * <p>
 * Author: yons
 * Date: 2019/03/08
 * Time: 00:13
 * Description:
 * Copyright © 2019年 com.zhujizheng. All rights reserved.
 */
@Service
@Slf4j
@Transactional(rollbackFor = RuntimeException.class)
public class PYEveryMomentServiceImpl implements PYEveryMomentService {

    @Autowired
    private PYEveryMomentMapper everyMomentMapper;
    @Autowired
    private PYEveryMomentImgMapper imgMapper;
    @Autowired
    private PYUserInfoMapper userInfoMapper;
    @Autowired
    private PYEveryMomentCommentMapper commentMapper;
    @Autowired
    private PYEveryMomentThumbupMapper thumbupMapper;
    @Autowired
    private CodeUtil codeUtil;
    @Autowired
    private AliPushService aliPushService;
    @Autowired
    private PYEveryMomentMsgMapper msgMapper;
    @Autowired
    private ApplicationEventPublisher publisher;

    private static final int DEFAULT_NUM = 10;

    @Override
    public List<PYEveryMomentVO> pullEveryMoment(PYEveryMomentPullDTO pullEveryMomentDTO) {
        Integer userId = pullEveryMomentDTO.getUserId();
        Integer loverId = pullEveryMomentDTO.getLoverId();
        String tag = pullEveryMomentDTO.getTag();
        Integer emIdInt = pullEveryMomentDTO.getEmId();
        String keyword = pullEveryMomentDTO.getKeyword();
        if (emIdInt == null) {
            log.info("emIdInt数据异常");
            return null;
        }
        int emId = codeUtil.dealInt(emIdInt);

        List<PYEveryMoment> everyMomentList = null;
        if (userId == null && loverId == null && tag != null) {
            // 查询指定类型的数据
            everyMomentList = everyMomentMapper.selectKongfuData(emId, tag, DEFAULT_NUM);
        } else if (userId != null && loverId != null && tag != null) {
            // 查询指定用户,指定类型的数据
            everyMomentList = everyMomentMapper.selectEveryMomentWithTag(userId, loverId, emId, tag, DEFAULT_NUM);
        } else if (userId != null && loverId != null && keyword != null) {
            // 搜索动态
            everyMomentList = everyMomentMapper.selectEveryMomentWithKeyword(userId, loverId, emId, keyword, DEFAULT_NUM);
        } else if (userId != null && loverId != null) {
            // 查询指定用户的数据
            everyMomentList = everyMomentMapper.selectEveryMoment(userId, loverId, emId, DEFAULT_NUM);
        } else {
            log.warn("pullEveryMoment数据异常");
            return null;
        }
        if (everyMomentList == null) {
            log.info("pullEveryMoment 查询动态集合为空" + pullEveryMomentDTO);
            return null;
        }
        // 动态VO集合
        List<PYEveryMomentVO> everyMomentVOList = new ArrayList<>();
        // 遍历所有动态模型
        for (PYEveryMoment everyMoment : everyMomentList) {
            // 获取某条动态模型
            // 根据动态模型获取动态VO
            Pair<PYEveryMomentVO, Integer> pair = PYEveryMomentVO.createVO(everyMoment, userInfoMapper, imgMapper, commentMapper, thumbupMapper);
            if (pair != null) {
                // 将动态VO添加到动态VO集合
                everyMomentVOList.add(pair.getLeft());
            } else {
                log.info("pullEveryMoment 根据动态模型获取动态VO为空" + everyMoment);
            }
        }
        return everyMomentVOList;
    }

    @Override
    public PYEveryMomentVO getEveryMomentByEmId(int emId) {
        log.info("emId = " + emId);
        // 根据动态id获取动态模型
        PYEveryMoment everyMoment = everyMomentMapper.selectEveryMomentByEmId(emId);
        // 根据动态模型获取动态VO
        Pair<PYEveryMomentVO, Integer> pair = PYEveryMomentVO.createVO(everyMoment, userInfoMapper, imgMapper, commentMapper, thumbupMapper);
        if (pair == null) {
            log.info("getEveryMomentByEmId 获取动态模型VO为空");
            return null;
        }
        return pair.getLeft();
    }

    @Override
    public PYEveryMomentVO pushEveryMoment(PYEveryMomentPushDTO pushDTO) {
        PYEveryMoment everyMoment = PYEveryMoment.createEveryMoment(pushDTO);
        int insertResult = everyMomentMapper.insertEveryMoment(everyMoment);
        if (insertResult == 0) {
            log.info("pushEveryMoment 插入动态失败" + everyMoment);
            return null;
        }
        if (pushDTO.getImgs() != null && pushDTO.getImgs().size() > 0) {
            List<PYEveryMomentPushDTO.PYPushEveryMomentImgDTO> imgDTOList = pushDTO.getImgs();
            log.info("imgDTOList = " + imgDTOList);
            for (PYEveryMomentPushDTO.PYPushEveryMomentImgDTO imgDTO : imgDTOList) {
                if (imgDTO.getType() == null) {
                    imgDTO.setType(1);
                }
                assert everyMoment != null;
                int result = imgMapper.insertImgWithEmId(everyMoment.getId(), imgDTO.getUrl(), imgDTO.getIdx(), imgDTO.getWidth(), imgDTO.getHeight(), imgDTO.getOrientation(), pushDTO.getUserId(), pushDTO.getTag(), imgDTO.getType(), pushDTO.getReleaseTime());
                if (result == 0) {
                    log.info("pushEveryMoment 插入动态的图片失败" + imgDTO + everyMoment);
                }
            }
        }
        /// 发出事件通知
        publisher.publishEvent(pushDTO);

        Pair<PYEveryMomentVO, Integer> pair = PYEveryMomentVO.createVO(everyMoment, userInfoMapper, imgMapper, commentMapper, thumbupMapper);
        if (pair == null) {
            log.info("pushEveryMoment 根据动态模型获取动态VO为空" + everyMoment);
            return null;
        }
        // 根据动态VO创建一个系统消息
        PYEveryMomentSysMsg sysMsg = PYEveryMomentSysMsg.createSystemMessage(pair.getLeft(), pair.getRight());
        // 插入系统消息并推送
        this.pushRemoteMessage(sysMsg);
        return pair.getLeft();
    }

    @Override
    public int deleteEveryMoment(PYEveryMomentDeleteDTO deleteEveryMomentDTO) {
        int result = everyMomentMapper.updateEveryMoment(deleteEveryMomentDTO.getEmId(), deleteEveryMomentDTO.getUserId());
        if (result == 0) {
            log.info("deleteEveryMoment 删除动态失败" + deleteEveryMomentDTO);
        }
        PYEveryMomentMsg sysMsg = msgMapper.selectMsgWithUserIdAndMsgTypeAndMsgTypeId(deleteEveryMomentDTO.getUserId(), 1, deleteEveryMomentDTO.getEmId());
        this.deleteSystemMessage(sysMsg);
        return result;
    }

    @Override
    public PYEveryMomentThumbupVO thumbupEveryMoment(PYEveryMomentThumbupDTO thumbupDTO) {
        log.info("thumbupDTO = " + thumbupDTO);
        List<PYEveryMomentThumbup> thumbupList = thumbupMapper.selectAllThumbupWithEmIdAndUserId(thumbupDTO.getEmId(), thumbupDTO.getFromUserId());
        log.info("thumbupList = " + thumbupList);
        int result;
        PYEveryMomentThumbup thumbup;
        AtomicBoolean needCreateMsg = new AtomicBoolean();
        if (thumbupList == null || thumbupList.size() == 0) {
            // 如果不能查到点赞数据,就插入一条新的点赞数据
            thumbup = PYEveryMomentThumbup.createThumbup(thumbupDTO);
            result = thumbupMapper.insertThumbupEveryMoment(thumbup);
            needCreateMsg.set(true);
        } else {
            // 如果能查到点赞数据,就更新旧的点赞数据,防止多次"点赞/取消点赞"产生大量点赞记录
            thumbup = thumbupList.get(0);
            result = thumbupMapper.updateThumbupEveryMoment(
                    thumbup.getId(),
                    thumbup.getEmId(),
                    thumbup.getFromUserId(),
                    thumbup.getToUserId(),
                    thumbup.getThumbupTime(),
                    0);
            needCreateMsg.set(false);
        }
        if (result == 0) {
            log.info("thumbupEveryMoment 更新或插入点赞数据失败" + thumbupList);
            return null;
        } else {
            PYEveryMomentThumbupVO thumbupVO = PYEveryMomentThumbupVO.createThumbupVO(thumbup, userInfoMapper);
            if (thumbupVO == null) {
                log.info("thumbupEveryMoment 获取点赞VO为空" + thumbup);
                return null;
            }
            if (needCreateMsg.get()) {
                // 创建一条系统消息
                PYEveryMomentThumbupSysMsg sysMsg = PYEveryMomentThumbupSysMsg.createSystemMessage(thumbupVO, everyMomentMapper, imgMapper, userInfoMapper);
                // 插入系统消息并推送
                this.pushRemoteMessage(sysMsg);
            } else {
                PYEveryMomentMsg sysMsg = msgMapper.selectMsgWithUserIdAndMsgTypeAndMsgTypeId(thumbupVO.getFromUserId(), 3, thumbupVO.getThumbupId());
                msgMapper.updateMsgIsRead(sysMsg.getMsgId(), false);
            }

            return thumbupVO;
        }
    }

    @Override
    public void dealThumbupEveryMoment(String dataString, WebSocketServer socketServer, String protocolNumber) {
        PYEveryMomentThumbupDTO thumbupDTO = (PYEveryMomentThumbupDTO) DTOUtils.createDTO(dataString, PYEveryMomentThumbupDTO.class);
        if (thumbupDTO == null) {
            log.info("dealThumbupEveryMoment 解析点赞数据异常" + dataString + protocolNumber);
            return;
        }
        PYEveryMomentThumbupVO thumbupVO = this.thumbupEveryMoment(thumbupDTO);
//        socketServer.send(thumbupVO, protocolNumber);
    }

    @Override
    public int cancelThumbupEveryMoment(PYEveryMomentCancelThumbupDTO cancelThumbupDTO) {
        int result = thumbupMapper.updateThumbupEveryMoment(cancelThumbupDTO.getThumbupId(), cancelThumbupDTO.getEmId(), cancelThumbupDTO.getFromUserId(), cancelThumbupDTO.getToUserId(), cancelThumbupDTO.getThumbupTime(), 1);
        if (result == 0) {
            log.info("cancelThumbupEveryMoment 更新点赞数据失败" + cancelThumbupDTO);
        }
        PYEveryMomentMsg sysMsg = msgMapper.selectMsgWithUserIdAndMsgTypeAndMsgTypeId(cancelThumbupDTO.getFromUserId(), 3, cancelThumbupDTO.getThumbupId());
        this.deleteSystemMessage(sysMsg);
        return result;
    }
    @Override
    public void dealCancelThumbupEveryMoment(String dataString, WebSocketServer socketServer, String protocolNumber) {
        log.info("dataString = " + dataString);
        PYEveryMomentCancelThumbupDTO cancelThumbupDTO = (PYEveryMomentCancelThumbupDTO)DTOUtils.createDTO(dataString, PYEveryMomentCancelThumbupDTO.class);
        log.info("cancelThumbupDTO = " + cancelThumbupDTO);
        if (cancelThumbupDTO == null) {
            log.info("dealCancelThumbupEveryMoment 解析取消点赞数据异常" + dataString + protocolNumber);
            return;
        }
        int result = this.cancelThumbupEveryMoment(cancelThumbupDTO);
//        socketServer.send(result, protocolNumber);
    }

    @Override
    public PYEveryMomentCommentVO commentEveryMoment(PYEveryMomentCommentDTO commentDTO) {
        PYEveryMomentComment comment = PYEveryMomentComment.createComment(commentDTO);
        log.info("comment = " + comment);
        int result = commentMapper.insertCommentEveryMoment(comment);
        log.info("result = " + result + "comment = " + comment);
        if (result == 0) {
            log.info("commentEveryMoment 插入评论数据失败" + commentDTO);
            return null;
        }
        PYEveryMomentCommentVO commentVO = PYEveryMomentCommentVO.createCommentVO(comment, userInfoMapper);
        if (commentVO == null) {
            log.info("commentEveryMoment 获取评论数据异常" + commentDTO);
            return null;
        }

        // 创建一条系统消息
        PYEveryMomentCommentSysMsg sysMsg = PYEveryMomentCommentSysMsg.createSystemMessage(commentVO, everyMomentMapper, imgMapper, userInfoMapper);
        // 插入系统消息并推送
        this.pushRemoteMessage(sysMsg);
        return commentVO;
    }

    @Override
    public int deleteCommentEveryMoment(PYEveryMomentDeleteCommentDTO deleteCommentDTO) {
        log.info("deleteCommentDTO = " + deleteCommentDTO);
        int result = commentMapper.updateCommentEveryMoment(deleteCommentDTO.getCommentId(), deleteCommentDTO.getEmId(), deleteCommentDTO.getFromUserId(), deleteCommentDTO.getToUserId(), deleteCommentDTO.getCommentTime());
        if (result == 0) {
            log.info("deleteCommentEveryMoment 删除评论失败" + deleteCommentDTO);
        } else {
            PYEveryMomentMsg sysMsg = msgMapper.selectMsgWithUserIdAndMsgTypeAndMsgTypeId(deleteCommentDTO.getFromUserId(), 2, deleteCommentDTO.getCommentId());
            this.deleteSystemMessage(sysMsg);
        }
        return result;
    }

    private void deleteSystemMessage(PYEveryMomentMsg sysMsg) {
        log.info("sysMsg = " + sysMsg);
        if (sysMsg == null) {
            return;
        }
        int result = msgMapper.updateMsg(sysMsg.getMsgId(), true);
        if (result == 0) {
            log.info("deleteSystemMessage 删除系统消息失败");
        }
    }

    @Override
    public List<PYEveryMomentImgVO> getImgListWithUserId(int userId) {
        log.info("getImgListWithUserId userId = " + userId);
        List<PYEveryMomentImg> imgList = imgMapper.selectImgListWithUserId(userId);
        List<PYEveryMomentImgVO> imgVOList = new ArrayList<>();
        for (PYEveryMomentImg img: imgList) {
            PYEveryMomentImgVO vo = PYEveryMomentImgVO.createImgVO(img);
            if (vo != null) {
                imgVOList.add(vo);
            }
        }
        return imgVOList;
    }

    /**
     * @Description: 推送远程消息
     * @Param: com.zhujizheng.IHome.generator.dao.PYSystemMessage
     * @return: æ— 
     * @Author: 朱吉峥
     * @Date: 2019/04/30
    */
    private void pushRemoteMessage(PYEveryMomentMsg sysMsg) {
        if (sysMsg == null) {
            log.info("pushRemoteMessage 创建一条系统消息失败");
            return;
        }
        if (sysMsg.getMsgId() == null) {
            // 插入一条系统消息
            int result = msgMapper.insertMsg(sysMsg);
            if (result == 0) {
                log.info("pushRemoteMessage 插入一条系统消息失败" + sysMsg);
                return;
            }
            log.info("pushRemoteMessage 插入一条系统消息成功:" + sysMsg);
        } else {
            // 更新一条系统消息
            int result = msgMapper.updateMsg(sysMsg.getMsgId(), false);
            if (result == 0) {
                log.info("pushRemoteMessage 更新一条系统消息失败" + sysMsg);
                return;
            }
        }

        // 获取未读消息
        List<PYEveryMomentMsg> list = msgMapper.selectUnreadMsgs(sysMsg.getLoverId());
        if (list == null || list.size() == 0) {
            log.info("pushRemoteMessage 获取未读消息列表异常" + list + sysMsg);
            return;
        }
        log.info("获取未读消息list = " + list);

        PYEveryMomentMsgVO msgVO = PYEveryMomentMsgVO.createVO(sysMsg, userInfoMapper);
        if (msgVO == null) {
            return;
        }
        if (null != msgVO.getContent() && msgVO.getNeedDecode()) {
            String result = AESUtil.commonDecrypt(msgVO.getContent());
            msgVO.setContent(result);
        }
        // 在线推送
        String sid = sysMsg.getLoverId().toString();
        WebSocketServer item = WebSocketServer.getWebSocketMap().get(sid);
        if (null == item) {
            // 离线推送
            log.info("离线推送:msgVO:" + msgVO + ", sysMsg.getLoverId() = " + sysMsg.getLoverId() + "list.size() = " + list.size());
            aliPushService.pushRemoteNotify(msgVO, sysMsg.getLoverId(), list.size());
            return;
        }
        log.info("在线推送:msgVO:" + msgVO + ", sid = " + sid);
        NetEveryMomentMsg netEveryMomentMsg = new NetEveryMomentMsg();
        netEveryMomentMsg.sendObject(msgVO, sid);
    }
}