package com.ccwangluo.ccim.manage;

import android.text.TextUtils;

import com.ccwangluo.ccim.CCIMClient;
import com.ccwangluo.ccim.listener.ResultEventCallback;
import com.ccwangluo.ccim.modle.Contact;
import com.ccwangluo.ccim.modle.ContactGroup;
import com.ccwangluo.ccim.modle.ContactRequestsRes;
import com.ccwangluo.ccim.modle.Dialog;
import com.ccwangluo.ccim.modle.MessageContent;
import com.ccwangluo.ccim.modle.NetStatus;
import com.ccwangluo.ccim.modle.PullContactsRes;
import com.ccwangluo.ccim.modle.SearchRes;
import com.ccwangluo.ccim.modle.User;
import com.google.gson.Gson;
import com.google.protobuf.util.JsonFormat;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.logging.Logger;

import ccim.protocol.Chat;
import ccim.protocol.ContactOuterClass;

public class ContactManager {
    private final Logger logger = Logger.getLogger(CCIMClient.class.getName());
    private SocketManager socketManager;
    private CallBackManager<Chat.ChatResponseMessage> callBackManager;
    private MessageManager messageManager;
    private ExecutorService executor;

    private final HashMap<Long, Contact> contacts = new HashMap<>();  //联系人列表
    private final HashMap<Long, ContactGroup> contactGroups = new HashMap<>();  //群组列表
    private final HashMap<Long, Dialog> dialogs = new HashMap<>();  //对话列表
    private final HashSet<Long> blocklist = new HashSet<Long>();  //对话列表


    public ContactManager(SocketManager socketManager, CallBackManager<Chat.ChatResponseMessage> callBackManager, MessageManager messageManager, ExecutorService executor) {
        this.socketManager = socketManager;
        this.callBackManager = callBackManager;
        this.messageManager = messageManager;
        this.executor = executor;
    }


    /**
     * 获取联系人列表
     */
    public void getContactList(ResultEventCallback<PullContactsRes> resultEventCallback, boolean isClearCache) {
        if (!isClearCache && (contacts.size() > 0 || contactGroups.size() > 0 || dialogs.size() > 0)) {
            PullContactsRes pullContactsRes = new PullContactsRes(contactGroups.values(), contacts.values(), dialogs.values(), blocklist);
            resultEventCallback.onSuccess(pullContactsRes);
            return;
        }
        Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
        builder.setPullContactsReq(Chat.PullContactsRequest.newBuilder()
                .build());
        int id = socketManager.sendRequest(builder);
        callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
            @Override
            public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
                if (chatResponseMessage.hasPullContactsRes()) {
                    Chat.PullContactsResponse pullContactsRes = chatResponseMessage.getPullContactsRes();
                    try {
                        String print = JsonFormat.printer().print(pullContactsRes);
                        PullContactsRes pullContactsRes1 = new Gson().fromJson(print, PullContactsRes.class);
                        contacts.clear();
                        contactGroups.clear();
                        dialogs.clear();
                        blocklist.clear();
                        if (pullContactsRes1.getContacts() != null) {
                            for (Contact contact : pullContactsRes1.getContacts()) {
                                contacts.put(contact.getContactUserId(), contact);
                            }
                        }
                        if (pullContactsRes1.getContactGroups() != null) {
                            for (ContactGroup contactGroup : pullContactsRes1.getContactGroups()) {
                                contactGroups.put(contactGroup.getGroupId(), contactGroup);
                            }
                        }

                        if (pullContactsRes1.getDialogs() != null) {
                            for (Dialog dialog : pullContactsRes1.getDialogs()) {
                                dialogs.put(dialog.getContactUserId(), dialog);
                            }
                        }

                        if (pullContactsRes1.getBlocklist() != null) {
                            blocklist.addAll(pullContactsRes1.getBlocklist());
                        }

                        messageManager.getOfflineMessage(new ResultEventCallback<Void>() {
                            @Override
                            public void onSuccess(Void unused) {
                                executor.execute(new Runnable() {
                                    @Override
                                    public void run() {
                                        for (Long aLong : dialogs.keySet()) {
                                            Dialog dialog = dialogs.get(aLong);
                                            Long offlineMessageCountByUserId = messageManager.getOfflineMessageCountByUserId(aLong, dialog.getReadMsgId());
                                            dialog.setUnreadCount(offlineMessageCountByUserId == null ? 0 : offlineMessageCountByUserId);
                                        }
                                        resultEventCallback.onSuccess(new PullContactsRes(contactGroups.values(), contacts.values(), dialogs.values(), blocklist));
                                    }
                                });
                            }

                            @Override
                            public void onFailed(int errorCode) {
                                resultEventCallback.onFailed(errorCode);
                            }
                        });
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }
            }

            @Override
            public void onFailed(int errorCode) {
                resultEventCallback.onFailed(errorCode);
            }
        });

    }


    /**
     * 搜索好友
     */
    public void searchUser(String userName, long userId, int page, int size, ResultEventCallback<SearchRes> resultEventCallback) {
        Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
        Chat.SearchRequest build = Chat.SearchRequest.newBuilder()
                .setUsername(userName)
                .setUserId(userId)
                .setPage(page)
                .setSize(size)
                .build();
        builder.setSearchReq(build);
        int id = socketManager.sendRequest(builder);
        callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
            @Override
            public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
                if (chatResponseMessage.hasSearchRes()) {
                    Chat.SearchResponse searchRes = chatResponseMessage.getSearchRes();
                    try {
                        String print = JsonFormat.printer().print(searchRes);
                        SearchRes searchRes1 = new Gson().fromJson(print, SearchRes.class);
                        resultEventCallback.onSuccess(searchRes1);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }
            }

            @Override
            public void onFailed(int errorCode) {
                resultEventCallback.onFailed(errorCode);
            }
        });
    }


    /**
     * 添加好友
     */
    public void addContact(Long userId, ResultEventCallback<Void> callback) {
        Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
        builder.setAddContactReq(Chat.AddContactRequest.newBuilder().setUserId(userId).build());
        int id = socketManager.sendRequest(builder);
        callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
            @Override
            public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
                if (chatResponseMessage.hasAddContactRes()) {
                    callback.onSuccess(null);
                }
            }

            @Override
            public void onFailed(int errorCode) {
                callback.onFailed(errorCode);
            }
        });

    }

    /**
     * 联系人申请列表
     */
    public void getContactReqList(ResultEventCallback<List<User>> callback) {
        Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
        builder.setContactRequestsReq(Chat.ContactRequestsRequest.newBuilder().build());
        int id = socketManager.sendRequest(builder);
        callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
            @Override
            public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
                if (chatResponseMessage.hasContactRequestsRes()) {
                    Chat.ContactRequestsResponse contactRequestsRes = chatResponseMessage.getContactRequestsRes();
                    try {
                        String print = JsonFormat.printer().print(contactRequestsRes);
                        logger.info(print);
                        ContactRequestsRes contactRequestsRes1 = new Gson().fromJson(print, ContactRequestsRes.class);
                        callback.onSuccess(contactRequestsRes1.getRequests());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }
            }

            @Override
            public void onFailed(int errorCode) {
                callback.onFailed(errorCode);
            }
        });

    }

    /**
     * 验证联系人申请
     */
    public void checkContactReq(Long reqUserId, boolean accept, ResultEventCallback<Void> callback) {
        Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
        Chat.CheckContactReqRequest checkContactReqRequest = Chat.CheckContactReqRequest.newBuilder()
                .setReqUserId(reqUserId)
                .setAccept(accept)
                .build();
        builder.setCheckContactReqReq(checkContactReqRequest);
        int id = socketManager.sendRequest(builder);
        callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
            @Override
            public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
                if (chatResponseMessage.hasCheckContactReqRes()) {
                    ContactOuterClass.Contact newContact = chatResponseMessage.getCheckContactReqRes().getNewContact();
                    try {
                        String print = JsonFormat.printer().print(newContact);
                        if (accept) {
                            Contact contact = new Gson().fromJson(print, Contact.class);
                            contacts.put(contact.getContactUserId(), contact);
                        }
                        callback.onSuccess(null);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

            @Override
            public void onFailed(int errorCode) {
                callback.onFailed(errorCode);
            }
        });
    }

    /**
     * 创建联系人群组
     */
    public void createContactGroup(String name, ResultEventCallback<Long> callback) {
        Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
        Chat.CreateContactGroupRequest createContactGroupRequest = Chat.CreateContactGroupRequest.newBuilder()
                .setName(name)
                .build();
        builder.setCreateContactGroupReq(createContactGroupRequest);
        int id = socketManager.sendRequest(builder);
        callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
            @Override
            public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
                if (chatResponseMessage.hasCreateContactGroupRes()) {
                    Chat.CreateContactGroupResponse createContactGroupRes = chatResponseMessage.getCreateContactGroupRes();
                    long groupId = createContactGroupRes.getGroupId();
                    contactGroups.put(groupId, new ContactGroup(groupId, name));
                    callback.onSuccess(groupId);
                }
            }

            @Override
            public void onFailed(int errorCode) {
                callback.onFailed(errorCode);
            }
        });
    }


    /**
     * 删除联系人群组
     */
    public void deleteContactGroup(Long groupId, ResultEventCallback<Void> callback) {
        Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
        builder.setDeleteContactGroupReq(ContactOuterClass.DeleteContactGroupRequest.newBuilder().setContactGroupId(groupId).build());
        int id = socketManager.sendRequest(builder);
        callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
            @Override
            public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
                contactGroups.remove(groupId);
                for (Map.Entry<Long, Contact> longContactEntry : contacts.entrySet()) {
                    Contact value = longContactEntry.getValue();
                    if (value.getContactGroupId().equals(groupId)) {
                        value.setContactGroupId(0L);
                    }
                }
                callback.onSuccess(null);
            }

            @Override
            public void onFailed(int errorCode) {
                callback.onFailed(errorCode);
            }
        });
    }


    /**
     * 移动联系人所在的群组
     */
    public void moveContactGroup(Long groupId, Long userId, ResultEventCallback<Void> callback) {
        Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
        Chat.MoveContactGroupRequest moveContactGroupRequest = Chat.MoveContactGroupRequest.newBuilder()
                .setContactGroupId(groupId)
                .setContactUserId(userId)
                .build();
        builder.setMoveContactGroupReq(moveContactGroupRequest);
        int id = socketManager.sendRequest(builder);
        callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
            @Override
            public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
                if (chatResponseMessage.hasMoveContactGroupRes()) {
                    Contact contact = contacts.get(userId);
                    if (contact != null) {
                        contact.setContactGroupId(groupId);
                    }
                    callback.onSuccess(null);
                }
            }

            @Override
            public void onFailed(int errorCode) {
                callback.onFailed(errorCode);
            }
        });
    }

    /**
     * 删除联系人
     */
    public void deleteContact(Long userId, ResultEventCallback<Void> callback) {
        Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
        Chat.DeleteContactRequest deleteContactRequest = Chat.DeleteContactRequest.newBuilder()
                .setContactUserId(userId)
                .build();
        builder.setDeleteContactReq(deleteContactRequest);
        int id = socketManager.sendRequest(builder);
        callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
            @Override
            public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
                contacts.remove(userId);
                dialogs.remove(userId);
                callback.onSuccess(null);
            }

            @Override
            public void onFailed(int errorCode) {
                callback.onFailed(errorCode);
            }
        });
    }

    /**
     * 拉黑联系人
     */
    public void blockContact(Long userId, ResultEventCallback<Void> callback) {
        Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
        ccim.protocol.User.BlockUserRequest blockContactRequest = ccim.protocol.User.BlockUserRequest.newBuilder()
                .setBlockedUserId(userId)
                .build();
        builder.setBlockUserReq(blockContactRequest);
        int id = socketManager.sendRequest(builder);
        callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
            @Override
            public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
                blocklist.add(userId);
                callback.onSuccess(null);
            }

            @Override
            public void onFailed(int errorCode) {
                callback.onFailed(errorCode);
            }
        });
    }

    /**
     * 举报违规用户
     */
    public void reportIllegalUser(String title, String content, Long userId, ResultEventCallback<Void> callback) {
        Chat.ChatRequestMessage.Builder builder = Chat.ChatRequestMessage.newBuilder();
        Chat.ReportIllegalUserRequest reportIllegalUserRequest = Chat.ReportIllegalUserRequest.newBuilder()
                .setContent(content)
                .setIllegalUserId(userId)
                .setTitle(title)
                .build();
        builder.setReportIllegalUserReq(reportIllegalUserRequest);
        int id = socketManager.sendRequest(builder);
        callBackManager.addCallBack(id, new ResultEventCallback<Chat.ChatResponseMessage>() {
            @Override
            public void onSuccess(Chat.ChatResponseMessage chatResponseMessage) {
                if (chatResponseMessage.hasReportIllegalUserRes()) {
                    logger.info(String.valueOf(chatResponseMessage));
                    callback.onSuccess(null);
                }
            }

            @Override
            public void onFailed(int errorCode) {
                callback.onFailed(errorCode);
            }
        });
    }

    /**
     * @param strangerDialog
     */
    public void putStrangerDialog(Dialog strangerDialog) {
        dialogs.put(strangerDialog.getContactUserId(), strangerDialog);
    }

    /**
     * 新增对话列表
     *
     * @param senderUserId
     * @param userName
     */
    public void putContactDialog(Long senderUserId, String userName) {
        if (!dialogs.containsKey(senderUserId)) {
            Dialog dialog = new Dialog();
            dialog.setContactUserId(senderUserId);
            Contact contact = contacts.get(senderUserId);
            if (contact != null) {
                dialog.setDialogType(Dialog.DialogType.FRIEND);
                dialog.setNetStatus(contact.getNetStatus());
                dialog.setPrivateId(contact.getPrivateId());
                dialog.setExtData(contact.getExtData());
                dialog.setContactUserName(contact.getContactUserName());
            } else {
                dialog.setDialogType(Dialog.DialogType.STRANGER);
                if (TextUtils.isEmpty(userName)) {
                    dialog.setContactUserName(userName);
                }
            }
            dialogs.put(dialog.getContactUserId(), dialog);
        }

    }

    /**
     * 新联系人
     *
     * @param contact
     */
    public void pushNewContact(Contact contact) {
        contacts.put(contact.getContactUserId(), contact);
        Dialog dialog = dialogs.get(contact.getContactUserId());
        if (dialog != null) {
            dialog.setDialogType(Dialog.DialogType.FRIEND);
        }
    }

    /**
     * 删除联系人
     *
     * @param contactUserId
     */
    public void pushDeleteContact(long contactUserId) {
        contacts.remove(contactUserId);
        dialogs.remove(contactUserId);
    }

    /**
     * 更新联系人网络状态
     *
     * @param contactUserId
     * @param netStatus
     */
    public void pushContactNetStatus(long contactUserId, NetStatus netStatus) {
        Contact contact = contacts.get(contactUserId);
        if (contact != null) {
            contact.setNetStatus(netStatus);
        }
        Dialog dialog = dialogs.get(contactUserId);
        if (dialog != null) {
            dialog.setNetStatus(netStatus);
        }
    }
}
