/*
 * /////////////////////////////////////////////////////////////////////////////////
 * //
 * // Copyright <2015>-<2016> Avaya Inc. All Rights Reserved.
 * //
 * // Usage of this source is bound to the terms described
 * // in assets/Licence.txt
 * //
 * // Avaya - Confidential & Proprietary. Use pursuant to your signed agreement
 * // or Avaya Policy
 * //
 * /////////////////////////////////////////////////////////////////////////////
 */

package com.avaya.odonnell3.AndroidChatTemplate_2_3.classes;

import android.support.annotation.Nullable;
import android.text.format.DateFormat;
import android.util.Log;
import com.avaya.odonnell3.AndroidChatTemplate_2_3.model.AgentIsTyping;
import com.avaya.odonnell3.AndroidChatTemplate_2_3.model.NewAgentFileTransfer;
import com.avaya.odonnell3.AndroidChatTemplate_2_3.model.NewAutomationMessageNotification;
import com.avaya.odonnell3.AndroidChatTemplate_2_3.model.NewCoBrowseNotification;
import com.avaya.odonnell3.AndroidChatTemplate_2_3.model.NewMessageNotification;
import com.avaya.odonnell3.AndroidChatTemplate_2_3.model.CloseConversationNotice;
import com.avaya.odonnell3.AndroidChatTemplate_2_3.model.CloseConversationRequest;
import com.avaya.odonnell3.AndroidChatTemplate_2_3.model.CustomerJsonWrapper;
import com.avaya.odonnell3.AndroidChatTemplate_2_3.model.NewMessageAck;
import com.avaya.odonnell3.AndroidChatTemplate_2_3.model.NewMessageRequest;
import com.avaya.odonnell3.AndroidChatTemplate_2_3.model.NewParticipant;
import com.avaya.odonnell3.AndroidChatTemplate_2_3.model.PagePush;
import com.avaya.odonnell3.AndroidChatTemplate_2_3.model.ParticipantLeave;
import com.avaya.odonnell3.AndroidChatTemplate_2_3.model.Pong;
import com.avaya.odonnell3.AndroidChatTemplate_2_3.model.RequestChatNotification;
import com.avaya.odonnell3.AndroidChatTemplate_2_3.model.NewChatRequest;
import com.avaya.odonnell3.AndroidChatTemplate_2_3.model.RouteCancel;
import com.avaya.odonnell3.AndroidChatTemplate_2_3.model.WsErrorMessage;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;

import java.io.IOException;
import java.util.Calendar;
import java.util.Locale;


public class MessageParser {

    public static String javaObjectToJson(Object o) {
        ObjectMapper mapper = new ObjectMapper();
        String jsonString = null;

        try {
            jsonString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(o);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            Log.e("Error", "error changing object to json string");
        }

        return jsonString;
    }

    public static CustomerJsonWrapper jsonStringToJava(String message) {

        CustomerJsonWrapper wrapper = new CustomerJsonWrapper();
        ObjectMapper mapper = new ObjectMapper();
        JsonNode root = null;
        JsonNode body;

        try {
            root = mapper.readTree(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
        body = root.get("body");

        String type = root.get("type").asText();
        wrapper.setType(type);
        String apiVersion = root.get("apiVersion").asText();
        wrapper.setApiVersion(apiVersion);

        String method = body.get("method").asText();

        switch (type) {

            case "request":
                wrapper.setBody(getRequestBody(mapper, body, method));
                break;
            case "error":
                wrapper.setBody(getErrorBody(mapper, body));
                break;
            case "notification":
                wrapper.setBody(getNotificationBody(mapper, body, method));
                break;
            case "acknowledgement":
                wrapper.setBody(getNewMessageAck(mapper, body));
                break;
            default:
                Log.e("Error", "message was not a |request | notification | error | acknowledgement");
                return null;
        }

        return wrapper;

    }

    @Nullable
    private static NewMessageAck getNewMessageAck(ObjectMapper mapper, JsonNode body) {
        NewMessageAck ack = null;
        try {
            ack = mapper.readValue(body.toString(),NewMessageAck.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ack;
    }

    private static Object getRequestBody(ObjectMapper mapper, JsonNode body, String method) {
        Object objectBody = null;
        try {
            switch (method) {
                case "requestChat":
                    objectBody = mapper.readValue(body.toString(), NewChatRequest.class);
                    break;
                case "newMessage":
                    objectBody = mapper.readValue(body.toString(), NewMessageRequest.class);
                    break;
                case "closeConversation":
                    objectBody = mapper.readValue(body.toString(), CloseConversationRequest.class);
                    break;
                case "participantLeave":
                    objectBody = mapper.readValue(body.toString(), ParticipantLeave.class);
                    break;
                default:

                    return null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return objectBody;
    }

    private static Object getErrorBody(ObjectMapper mapper, JsonNode body) {
        WsErrorMessage errorMessage = null;
        try {
            errorMessage = mapper.readValue(body.toString(), WsErrorMessage.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        Log.e("Error", "Error Message: " + errorMessage.toString());
        return errorMessage;
    }

    private static Object getNotificationBody(ObjectMapper mapper, JsonNode body, String method) {


        Object objectBody = null;
        try {
            switch (method) {
                case "requestChat":

                    objectBody = mapper.readValue(body.toString(), RequestChatNotification.class);
                    break;
                case "newParticipant":
                    objectBody = mapper.readValue(body.toString(), NewParticipant.class);
                    break;
                case "newMessage":

                    if (body.toString()
                            .contains("message")) {
                        try {
                            objectBody = mapper.readValue(body.toString(), NewMessageNotification.class);
                        }catch(UnrecognizedPropertyException e){
                            objectBody = mapper.readValue(body.toString(), NewAutomationMessageNotification.class);
                        }
                    } else {
                        objectBody = mapper.readValue(body.toString(), NewMessageAck.class);
                    }
                    break;
                case "participantLeave":
                    objectBody = mapper.readValue(body.toString(), ParticipantLeave.class);
                    break;
                case "closeConversation":
                    objectBody = mapper.readValue(body.toString(), CloseConversationNotice.class);
                    break;
                case "newPushPageMessage":
                    objectBody = mapper.readValue(body.toString(), PagePush.class);
                    break;
                case "isTyping":
                    objectBody = mapper.readValue(body.toString(), AgentIsTyping.class);
                    break;
                case "routeCancel":
                    objectBody = mapper.readValue(body.toString(), RouteCancel.class);
                    break;
                case "pong":
                    objectBody = new Pong();
                    break;
                case "newAgentFileTransfer" :
                    objectBody = mapper.readValue(body.toString(), NewAgentFileTransfer.class);
                    break;
                case "newCoBrowseSessionKeyMessage" :
                    objectBody = mapper.readValue(body.toString(), NewCoBrowseNotification.class);
                    Log.v("Info", "newCoBrowseSessionKeyMessage " + body.toString());
                    break;
                default:
                    Log.e("Error", "Could not match notification: " + method);
                    return null;

            }// end of switch
        } catch (IOException e) {
            e.printStackTrace();
        }
        return objectBody!=null?objectBody:new Object();

    }

    public static String getTime(String timeStamp) {
        Calendar calendar = Calendar.getInstance(Locale.ENGLISH);
        if(timeStamp.equalsIgnoreCase("")) {
            timeStamp = calendar.getTimeInMillis() + "";
        }
        calendar.setTimeInMillis(Long.parseLong(timeStamp));
        String time = DateFormat.format("h:mm a", calendar).toString();
        Log.v("Info", "got time from Timestamp? " + time);
        return time;
    }
}

