package com.rv.im.xmpp;

import android.annotation.SuppressLint;
import android.os.Handler;
import android.text.TextUtils;

import com.rv.im.ImService;
import com.rv.im.db.table.ChatMessage;
import com.rv.im.log.LogUtil;
import com.rv.im.xmpp.listener.ChatMessageListener;

import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smackx.receipts.DeliveryReceiptManager;
import org.jivesoftware.smackx.receipts.ReceiptReceivedListener;

import java.util.HashMap;
import java.util.Map;

public class ReceiptManager {
    public static final int MESSAGE_DELAY = 10 * 1000; // 等待消息回执， 超时时间
    private static final int RECEIPT_NO = 0x1; // 没有收到回执
    private static final int RECEIPT_YES = 0x2;// 收到回执
    /**
     * 处理消息回执
     */
    public static Map<String, ReceiptObj> mReceiptMap = new HashMap<String, ReceiptObj>();
    private ImService mService;
    private XMPPTCPConnection mConnection;
    private String mLoginUserId;// 用于切换用户后，判断是否清除回执内容
    /**
     * 重发次数表
     */
    private Map<String, Integer> mReSendMap = new HashMap<String, Integer>();


    @SuppressLint("HandlerLeak")
    private Handler mReceiptMapHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            String packetId = (String) msg.obj;
            if (TextUtils.isEmpty(packetId)) {
                return;
            }

            ReceiptObj obj = mReceiptMap.get(packetId); // 接收到message先从map中去除对应键值的消息
            if (obj == null || obj.msg == null) {// 没有取出表示没有该消息
                return;
            }

            if (msg.what == RECEIPT_NO) { // 认为这条消息未发送成功,已超时
                ListenerManager.getInstance().notifyMessageSendStateChange(packetId, ChatMessageListener.MESSAGE_SEND_FAILED);
            } else if (msg.what == RECEIPT_YES) {// 认为发送成功
                ListenerManager.getInstance().notifyMessageSendStateChange(packetId, ChatMessageListener.MESSAGE_SEND_SUCCESS);
            }
            mReceiptMap.remove(packetId);
        }
    };

    ReceiptReceivedListener mReceiptReceivedListener = (fromJid, toJid, receiptId, receipt) -> {

        mReceiptMapHandler.removeMessages(RECEIPT_NO, receiptId);
        android.os.Message handlerMsg = mReceiptMapHandler.obtainMessage(RECEIPT_YES);
        handlerMsg.obj = receiptId;
        mReceiptMapHandler.sendMessage(handlerMsg);
        LogUtil.e("msg", "收到消息回执:fromJid=" + fromJid + "-----toJid=" + toJid + "-----receiptId=" + receiptId);
    };


    public void addWillSendMessage(final String toUserId
            , final ChatMessage xmppMessage, SendType sendType, String content) {

        // 将之前可能存在的回执缓存清除掉
        if (mReceiptMap.containsKey(xmppMessage.getPackId())) {
            ReceiptObj oldObj = mReceiptMap.get(xmppMessage.getPackId());
            mReceiptMapHandler.removeMessages(RECEIPT_NO, oldObj);
            mReceiptMap.remove(xmppMessage.getPackId());
        }

        // 将这个回执对象缓存起来，这样在接到回执的时候容易定位到是发给谁的哪条消息
        ReceiptObj obj = new ReceiptObj();
        obj.toUserId = toUserId;
        obj.msg = xmppMessage;
        obj.sendType = sendType;
        obj.Read_msg_pid = content;
        mReceiptMap.put(xmppMessage.getPackId(), obj);// 记录一条新发送出去的消息(还没有接收到回执)

        android.os.Message handlerMsg = mReceiptMapHandler.obtainMessage(RECEIPT_NO); // 默认先标记没有接收到回执
        handlerMsg.obj = xmppMessage.getPackId();
        mReceiptMapHandler.sendMessageDelayed(handlerMsg, MESSAGE_DELAY);// 延迟二十秒发送
        LogUtil.e("msg", "产生一条消息，等待回执..." + "xmppMessage.getPacketId()--->" + xmppMessage.getPackId()
                + " ，chatMessage.getPacketId()--->" + xmppMessage.getPackId() + " ，type--->" + xmppMessage.getMessageType()
                + " ，content--->" + xmppMessage.getContent());
    }

    public ReceiptManager(ImService service, XMPPTCPConnection connection) {
        mService = service;
        mConnection = connection;
        mLoginUserId = service.getUserId();

        DeliveryReceiptManager mDeliveryReceiptManager = DeliveryReceiptManager.getInstanceFor(mConnection);
        // 自动发送消息回执
        mDeliveryReceiptManager.setAutoReceiptMode(DeliveryReceiptManager.AutoReceiptMode.always);
        // 添加消息回执监听
        mDeliveryReceiptManager.addReceiptReceivedListener(mReceiptReceivedListener);
    }

    public void reset() {
        String userId = mService.getUserId();
        if (!mLoginUserId.equals(userId)) {
            mLoginUserId = userId;
            mReceiptMap.clear();
        }
    }

    /**
     * 发送的消息类型，用于类型判断和消息回执的分发
     */
    public enum SendType {
        NORMAL, PUSH_NEW_FRIEND
    }

    class ReceiptObj {
        String toUserId;    // 普通消息和新朋友消息公用
        ChatMessage msg;    // 用于普通消息和新朋友消息公用
        SendType sendType;  // 用于分发普通消息和新朋友消息的回执
        int Read;           // 用于标记此消息是否为已读回执消息
        String Read_msg_pid;// 被回执消息的packetId
    }
}
