using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Proyecto26;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace XenseAR {

[JsonConverter(typeof(SerializableDictionaryConverter))]
public class SerializableDictionary : Dictionary<string, object>
{
}

public class SerializableDictionaryConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var dictionary = value as SerializableDictionary;
        if (dictionary != null)
        {
            JObject jo = new JObject();
            foreach (var kvp in dictionary)
            {
                jo.Add(kvp.Key, JToken.FromObject(kvp.Value));
            }
            jo.WriteTo(writer);
        }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        var dictionary = new SerializableDictionary();
        foreach (var kvp in jo)
        {
            dictionary.Add(kvp.Key, kvp.Value);
        }
        return dictionary;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(SerializableDictionary);
    }
}

public class AnalyticsSender : MonoSingleton<AnalyticsSender>
{

    Dictionary<string, object> templateParameters = new Dictionary<string, object>();

    List<AnalyticData> data = new List<AnalyticData>();

    Dictionary<string, string> templateToken = new Dictionary<string, string>();

    private void Start()
    {
        templateParameters.Add("platform", Application.platform.ToString());
        templateParameters.Add("version", Application.version); 
        templateParameters.Add("deviceModel", SystemInfo.deviceModel);
        templateParameters.Add("deviceName", SystemInfo.deviceName);
        templateParameters.Add("deviceType", SystemInfo.deviceType.ToString());
        templateParameters.Add("deviceUniqueIdentifier", SystemInfo.deviceUniqueIdentifier);
        InvokeRepeating("SendListEvent", 0, 5);
    }

    private void OnEnable()
    {
        //change templateParam if key "token" exist in templateParameters, else add it
        if (templateParameters.ContainsKey("token"))
        {
            //random value
            templateParameters["token"] = Guid.NewGuid().ToString();
        }
        else
        {
            templateParameters.Add("token", Guid.NewGuid().ToString());
        }
    }

    private void OnApplicationPause(bool pause)
    {
        if (!pause)
        {
            //change templateParam if key "token" exist in templateParameters, else add it
            if (templateParameters.ContainsKey("token"))
            {
                //random value
                templateParameters["token"] = Guid.NewGuid().ToString();
            }
            else
            {
                templateParameters.Add("token", Guid.NewGuid().ToString());
            }
        }
    }

    public void AddParameter(string name, object value)
    {
        templateParameters.Add(name, value);
    }

    void SendListEvent()
    {

        List<SerializableDictionary> keyValuePairs = new List<SerializableDictionary>();

        foreach (var item in data)
        {
            var serializableDict = new SerializableDictionary();
            foreach (var kvp in item.data)
            {
                serializableDict.Add(kvp.Key, kvp.Value);
            }
            keyValuePairs.Add(serializableDict);
        }

        if (keyValuePairs.Count > 0)
        {
            LogServices.Instance.Post(new RequestHelper
            {
                SimpleForm = new Dictionary<string, string>
                {
                    {"event", "listEvent" },
                    {"data", JsonConvert.SerializeObject(keyValuePairs, Formatting.Indented) }
                }
            }).Then(response => Debug.Log("Log event: " + response.Text));
            data.Clear();
        }
    }

    public void SendEvent(string eventName)
    {
        Dictionary<string, object> parameters = new Dictionary<string, object>();
#if !UNITY_EDITOR && !DEVELOPMENT_BUILD
        //Add templateParameters to parameters
        parameters.Add("timestamp", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss zzz"));
        parameters.Add("event", eventName);
        foreach (var templateParameter in templateParameters)
        {
            parameters.Add(templateParameter.Key, templateParameter.Value);
        }
        data.Add(new AnalyticData { eventName = eventName, data = parameters });
#endif
    }

    private IEnumerator SendEventCoroutine(string eventName)
    {     
        
        Dictionary<string, object>  parameters = new Dictionary<string, object>();
        //Add templateParameters to parameters, set again the timeStamp of templateParameters
        parameters.Add("timestamp", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
        foreach (var templateParameter in templateParameters)
        {
            parameters.Add(templateParameter.Key, templateParameter.Value);
        }

        var serializableDict = new SerializableDictionary();
        foreach (var kvp in parameters)
        {
            serializableDict.Add(kvp.Key, kvp.Value);
        }

        LogServices.Instance.Post(new RequestHelper
        {
            SimpleForm = new Dictionary<string, string>
            {
                {"event", eventName },
                {"data", JsonConvert.SerializeObject(serializableDict, Formatting.Indented) }
            }
        }).Then(response => Debug.Log("Log event: " + response.Text));
        yield return null;
    }

    public void SendEvent(string eventName, Dictionary<string, object> parameters)
    {
#if !UNITY_EDITOR && !DEVELOPMENT_BUILD
//add templateParameters to parameters
        parameters.Add("timestamp", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss zzz"));
        parameters.Add("event", eventName);
        foreach (var templateParameter in templateParameters)
        {
            parameters.Add(templateParameter.Key, templateParameter.Value);
        }
        data.Add(new AnalyticData { eventName = eventName, data = parameters });
#endif
    }

    public void SendEvent(string eventName, string tokenName, bool renewToken = false)
    {
        Dictionary<string, object> parameters = new Dictionary<string, object>();

        if (renewToken)
        {
            if (templateToken.ContainsKey(tokenName))
            {
                //random value
                templateToken[tokenName] = Guid.NewGuid().ToString();
            }
            else
            {
                templateToken.Add(tokenName, Guid.NewGuid().ToString());
            }
        }

        if (templateToken.ContainsKey(tokenName))
        {
            if (templateParameters.ContainsKey("taskToken"))
            {
                //random value
                templateParameters["taskToken"] = templateToken[tokenName];
            }
            else
            {
                templateParameters.Add("taskToken", templateToken[tokenName]);
            }
        }

#if !UNITY_EDITOR && !DEVELOPMENT_BUILD
        //Add templateParameters to parameters
        parameters.Add("timestamp", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss zzz"));
        parameters.Add("event", eventName);
        foreach (var templateParameter in templateParameters)
        {
            parameters.Add(templateParameter.Key, templateParameter.Value);
        }
        data.Add(new AnalyticData { eventName = eventName, data = parameters });
#endif

    }

    private IEnumerator SendEventCoroutine(string eventName, Dictionary<string, object> parameters)
    {

        //Add templateParameters to parameters, set again the timeStamp of templateParameters
        parameters.Add("timestamp", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
        foreach (var templateParameter in templateParameters)
        {
            parameters.Add(templateParameter.Key, templateParameter.Value);
        }

        var serializableDict = new SerializableDictionary();
        foreach (var kvp in parameters)
        {
            serializableDict.Add(kvp.Key, kvp.Value);
        }
        string json = JsonConvert.SerializeObject(serializableDict, Formatting.Indented);
        LogServices.Instance.Post(new Proyecto26.RequestHelper
        {
            SimpleForm = new Dictionary<string, string>
            {
                {"event", eventName },
                {"data",json }
            }
        }).Then(response => Debug.Log("Log event: " + response.Text));
        yield return null;
    }
}
}
