package com.chatsdk.dispatch;

import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.chatsdk.common.ExtSdkCallback;
import io.agora.chat.ChatClient;
import io.agora.chat.CmdMessageBody;
import io.agora.chat.CombineMessageBody;
import io.agora.chat.Conversation;
import io.agora.chat.CustomMessageBody;
import io.agora.chat.FileMessageBody;
import io.agora.chat.ImageMessageBody;
import io.agora.chat.LocationMessageBody;
import io.agora.chat.ChatMessage;
import io.agora.chat.MessageBody;
import io.agora.chat.NormalFileMessageBody;
import io.agora.chat.TextMessageBody;
import io.agora.chat.VideoMessageBody;
import io.agora.chat.VoiceMessageBody;
import io.agora.exceptions.ChatException;
import java.util.HashMap;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class ExtSdkWrapper {

    protected static void onSuccess(@NonNull ExtSdkCallback callback, @NonNull String methodType,
                                    @Nullable Object object) {
        Log.d(TAG, "onSuccess: " + methodType + ": " + (object != null ? object : ""));
        Map<String, Object> data = new HashMap<>();
        if (object != null) {
            data.put(methodType, object);
        }
        callback.success(data);
    }

    public static void onError(@NonNull ExtSdkCallback callback, @NonNull Object e, @Nullable Object ext) {
        Log.d(TAG, "onError: " + e + ": " + (ext != null ? ext : ""));
        Map<String, Object> data = new HashMap<>();
        if (e instanceof ChatException) {
            data.put("error", ExtSdkExceptionHelper.toJson((ChatException)e));
        } else if (e instanceof Integer) {
            data.put("error", ExtSdkErrorHelper.toJson((int)e, ext != null ? ext.toString() : ""));
        } else if (e instanceof JSONException) {
            data.put("error", ExtSdkJSONExceptionHelper.toJson((JSONException)e));
        } else {
            data.put("error", "no implement");
        }
        callback.success(data);
    }

    protected static void onReceive(@NonNull String methodType, @Nullable Object data) {
        Log.d(TAG, "onReceive: " + methodType + ": " + (data != null ? data : ""));
        ExtSdkDispatch.getInstance().onReceive(methodType, data);
    }

    protected void mergeMessageBody(MessageBody msgBody, ChatMessage dbMsg) throws JSONException {
        if (dbMsg.getType() == ChatMessage.Type.TXT) {
            TextMessageBody text = (TextMessageBody)msgBody;
            TextMessageBody dbtext = (TextMessageBody)dbMsg.getBody();
            dbtext.setMessage(text.getMessage());
            dbtext.setTargetLanguages(text.getTargetLanguages());
            dbMsg.setBody(dbtext);
        } else if (dbMsg.getType() == ChatMessage.Type.CMD) {
            CmdMessageBody cmd = (CmdMessageBody)msgBody;
            CmdMessageBody dbcmd = (CmdMessageBody)dbMsg.getBody();
            dbcmd.deliverOnlineOnly(cmd.isDeliverOnlineOnly());
            dbMsg.setBody(dbcmd);
        } else if (dbMsg.getType() == ChatMessage.Type.IMAGE) {
            ImageMessageBody image = (ImageMessageBody)msgBody;
            ImageMessageBody dbimage = (ImageMessageBody)dbMsg.getBody();
            dbimage.setFileName(image.getFileName());
            dbimage.setLocalUrl(image.getLocalUrl());
            dbimage.setRemoteUrl(image.getRemoteUrl());
            dbimage.setSecret(image.getSecret());
            dbimage.setFileLength(image.getFileSize());
            dbimage.setDownloadStatus(image.downloadStatus());
            dbimage.setSendOriginalImage(image.isSendOriginalImage());
            dbimage.setThumbnailLocalPath(image.thumbnailLocalPath());
            dbimage.setThumbnailDownloadStatus(image.thumbnailDownloadStatus());
            dbimage.setThumbnailUrl(image.getThumbnailUrl());
            //        dbimage.setThumbnailSize(image.getWidth(), image.getHeight());
            dbMsg.setBody(dbimage);
        } else if (dbMsg.getType() == ChatMessage.Type.VOICE) {
            VoiceMessageBody voice = (VoiceMessageBody)msgBody;
            VoiceMessageBody dbvoice = (VoiceMessageBody)dbMsg.getBody();
            dbvoice.setFileName(voice.getFileName());
            dbvoice.setLocalUrl(voice.getLocalUrl());
            dbvoice.setRemoteUrl(voice.getRemoteUrl());
            dbvoice.setSecret(voice.getSecret());
            dbvoice.setFileLength(voice.getFileSize());
            dbvoice.setDownloadStatus(voice.downloadStatus());
            dbMsg.setBody(dbvoice);
        } else if (dbMsg.getType() == ChatMessage.Type.VIDEO) {
            VideoMessageBody video = (VideoMessageBody)msgBody;
            VideoMessageBody dbvideo = (VideoMessageBody)dbMsg.getBody();
            dbvideo.setFileName(video.getFileName());
            dbvideo.setLocalUrl(video.getLocalUrl());
            dbvideo.setRemoteUrl(video.getRemoteUrl());
            dbvideo.setSecret(video.getSecret());
            dbvideo.setDownloadStatus(video.downloadStatus());
            dbvideo.setVideoFileLength(video.getVideoFileLength());
            dbvideo.setThumbnailUrl(video.getThumbnailUrl());
            dbvideo.setThumbnailSize(video.getThumbnailWidth(), video.getThumbnailHeight());
            dbvideo.setLocalThumb(video.getLocalThumb());
            dbvideo.setThumbnailSecret(video.getThumbnailSecret());
            dbvideo.setThumbnailDownloadStatus(video.thumbnailDownloadStatus());
            dbMsg.setBody(video);
        } else if (dbMsg.getType() == ChatMessage.Type.LOCATION) {
            LocationMessageBody location = (LocationMessageBody)msgBody;
            dbMsg.setBody(location);
        } else if (dbMsg.getType() == ChatMessage.Type.FILE) {
            NormalFileMessageBody file = (NormalFileMessageBody)msgBody;
            FileMessageBody dbfile = (FileMessageBody)dbMsg.getBody();
            dbfile.setFileName(file.getFileName());
            dbfile.setLocalUrl(file.getLocalUrl());
            dbfile.setRemoteUrl(file.getRemoteUrl());
            dbfile.setSecret(file.getSecret());
            dbfile.setDownloadStatus(file.downloadStatus());
            dbfile.setFileLength(file.getFileSize());
            dbMsg.setBody(dbfile);
        } else if (dbMsg.getType() == ChatMessage.Type.CUSTOM) {
            CustomMessageBody cutom = (CustomMessageBody)msgBody;
            dbMsg.setBody(cutom);
        } else if (dbMsg.getType() == ChatMessage.Type.COMBINE) {
            CombineMessageBody combine = (CombineMessageBody)msgBody;
            dbMsg.setBody(combine);
        }
    }

    protected void mergeMessage(ChatMessage msg, ChatMessage dbMsg) throws JSONException {
        dbMsg.setMsgTime(msg.getMsgTime());
        dbMsg.setLocalTime(msg.localTime());
        dbMsg.setStatus(msg.status());
        dbMsg.setAcked(msg.isAcked());
        dbMsg.setIsChatThreadMessage(msg.isChatThreadMessage());
        dbMsg.setIsNeedGroupAck(msg.isNeedGroupAck());
        dbMsg.setDeliverAcked(msg.isDelivered());
        dbMsg.setUnread(msg.isUnread());
        dbMsg.setListened(msg.isListened());
        dbMsg.setReceiverList(msg.receiverList());
        // dbMsg.setPriority(msg.setPriority());
        dbMsg.deliverOnlineOnly(msg.isDeliverOnlineOnly());
        Map<String, Object> list = msg.getAttributes();
        if (!list.isEmpty()) {
            JSONObject jsonParams = new JSONObject(list);
            for (Map.Entry<String, Object> entry : list.entrySet()) {
                String key = entry.getKey();
                Object result = entry.getValue();
                if (result.getClass().getSimpleName().equals("Integer")) {
                    dbMsg.setAttribute(key, (Integer)result);
                } else if (result.getClass().getSimpleName().equals("Boolean")) {
                    dbMsg.setAttribute(key, (Boolean)result);
                } else if (result.getClass().getSimpleName().equals("Long")) {
                    dbMsg.setAttribute(key, (Long)result);
                } else if (result.getClass().getSimpleName().equals("Double") ||
                           result.getClass().getSimpleName().equals("Float")) {
                    dbMsg.setAttribute(key, (Double)result);
                } else if (result.getClass().getSimpleName().equals("JSONObject")) {
                    dbMsg.setAttribute(key, (JSONObject)result);
                } else if (result.getClass().getSimpleName().equals("JSONArray")) {
                    dbMsg.setAttribute(key, (JSONArray)result);
                } else {
                    dbMsg.setAttribute(key, jsonParams.getString(key));
                }
            }
        }
        dbMsg.setBody(msg.getBody());
    }

    protected Conversation getConversation(JSONObject params) throws JSONException {
        String convId = params.getString("convId");
        Conversation.ConversationType convType = ExtSdkConversationHelper.typeFromInt(params.getInt("convType"));
        boolean isChatThread = params.optBoolean("isChatThread", false);
        boolean createIfNotExists = params.optBoolean("createIfNeed", true);
        return ChatClient.getInstance().chatManager().getConversation(convId, convType, createIfNotExists, isChatThread);
    }

    protected Conversation getConversationFromMessage(ChatMessage message) {
        boolean createConv = message.getType() != ChatMessage.Type.CMD;
        return ChatClient.getInstance().chatManager().getConversation(
            message.conversationId(), Conversation.msgType2ConversationType(message.getTo(), message.getChatType()),
            createConv, message.isChatThreadMessage());
    }

    protected static boolean checkMessageParams(ChatMessage msg, String channelName, ExtSdkCallback result)
        throws JSONException {
        if (msg == null) {
            ExtSdkWrapper.onError(result, 1, "The message does not exist.");
            return true;
        }
        return false;
    }

    protected static boolean getMessageParams(ChatMessage msg, String channelName, ExtSdkCallback result)
        throws JSONException {
        if (msg == null) {
            ExtSdkWrapper.onSuccess(result, channelName, null);
            return true;
        }
        return false;
    }

    private static final String TAG = "EMWrapper";
}
