using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEditor;
using FVS;
using LitJson;

public class FVSUnityEditor : Editor
{
    public static void AddFVSMain()
    {
        if (GameObject.Find("FVSMain") != null) return;
        GameObject fvsMain = new GameObject("FVSMain");
        Undo.RegisterCreatedObjectUndo(fvsMain, "FVSMain");
        fvsMain.AddComponent<FVSUnityReact>();
        fvsMain.AddComponent<FVSActionManager>();
        Selection.activeGameObject = fvsMain;
    }

    public static void CreateFVSUnitySDKPackage()
    {
        string fileName = "fvs-unity-sdk." + Version.GetCode() + ".unitypackage";
        string pathName = "Assets/FVS-Unity";

        AssetDatabase.ExportPackage(pathName, fileName, ExportPackageOptions.Recurse);
        Application.OpenURL("file:///" + Path.Combine(Application.dataPath, "../"));
    }

    public static void CreateFVSUnityConfig()
    {
        if (FVSUnityReact.Instance == null)
        {
            Debug.LogError(EditorL10n.Get("Msg_AddFVSFirst"));
            return;
        }

        JsonData unityConfig = new JsonData();

        unityConfig["scene"] = AddSceneConfig();
        unityConfig["data"] = AddDataConfig();
        unityConfig["style"] = AddStyleConfig();
        unityConfig["action"] = AddActionConfig();
        unityConfig["event"] = AddEventConfig();
        OverwriteLocalizationJson(unityConfig);

        string fvsUnityConfig = unityConfig.ToJson();

        FVSUnityReact.Instance.jsonConfig = fvsUnityConfig;
        Debug.Log(BaseUtils.JsonStringFormat(fvsUnityConfig));

        // 直接更新输入框的值, 不会触发sceneDirty, 即最终的场景配置不会被修改, 这里强制触发一下, 打包的时候让用户保存.
        EditorApplication.MarkSceneDirty();
    }

    private static JsonData AddEventConfig()
    {
        if (FVSUnityReact.Instance.events.Length == 0)
        {
            return null;
        }

        JsonData eventConfigs = new JsonData();

        foreach (var eventInfo in FVSUnityReact.Instance.events)
        {
            JsonWriter writer = new JsonWriter();
            writer.WriteObjectStart();
            writer.WritePropertyName("name");
            writer.Write(eventInfo.name);
            writer.WritePropertyName("displayName");
            writer.Write(eventInfo.displayName);
            writer.WritePropertyName("parameters");
            writer.WriteArrayStart();
            foreach (var parameter in eventInfo.parameters)
            {
                writer.WriteObjectStart();
                writer.WritePropertyName("key");
                writer.Write(parameter.key);
                writer.WritePropertyName("displayName");
                writer.Write(parameter.displayName);
                writer.WriteObjectEnd();
            }
            writer.WriteArrayEnd();
            writer.WriteObjectEnd();
            eventConfigs.Add(JsonMapper.ToObject(writer.ToString()));
        }


        JsonData unityEvent = new JsonData();
        unityEvent["value"] = eventConfigs;

        return unityEvent;
    }

    private static JsonData AddActionConfig()
    {

        if (FVSUnityReact.Instance.actions.Length == 0)
        {
            return null;
        }

        JsonData actionConfigs = new JsonData();

        foreach (var action in FVSUnityReact.Instance.actions)
        {
            JsonWriter writer = new JsonWriter();
            writer.WriteObjectStart();
            writer.WritePropertyName("name");
            writer.Write(action.name);
            writer.WritePropertyName("displayName");
            writer.Write(action.displayName);
            writer.WriteObjectEnd();
            actionConfigs.Add(JsonMapper.ToObject(writer.ToString()));
        }

        JsonData unityAction = new JsonData();
        unityAction["value"] = actionConfigs;
        return unityAction;

    }

    private static JsonData AddSceneConfig()
    {
        FVSSceneConfig config = FVSUnityReact.Instance.sceneConfig;
        if (config.scenes == null) return null;
        if (config.scenes.Length == 0)
        {
            return null;
        }

            JsonWriter writer = new JsonWriter();
        writer.WriteObjectStart();
        writer.WritePropertyName("current");
        writer.Write(config.current);
        writer.WriteObjectEnd();

        JsonData sceneConfig = JsonMapper.ToObject(writer.ToString());

        JsonData sceneList = new JsonData();

        foreach (var item in config.scenes)
        {
            JsonWriter writer2 = new JsonWriter();
            writer2.WriteObjectStart();
            writer2.WritePropertyName("name");
            writer2.Write(item.name);
            writer2.WritePropertyName("displayName");
            writer2.Write(item.displayName);
            writer2.WriteObjectEnd();
            sceneList.Add(JsonMapper.ToObject(writer2.ToString()));
        }
        sceneConfig["scenes"] = sceneList;

        JsonData unityScene= new JsonData();
        unityScene["value"] = sceneConfig;
        return unityScene;
    }

    private static JsonData AddDataConfig()
    {
        FVSBaseData<SingleTableDataConfig>[] dataComponents = GameObject.FindObjectsOfType<FVSBaseData<SingleTableDataConfig>>();
        if (dataComponents.Length == 0)
        {
            return null;
        }

        JsonData dataConfigs = new JsonData();

        foreach (FVSBaseData<SingleTableDataConfig> dataComponent in dataComponents)
        {
            SingleTableDataConfig config = dataComponent.GetDataConfig();
            JsonWriter writer = new JsonWriter();
            writer.WriteObjectStart();
            writer.WritePropertyName("gameObject");
            writer.Write(dataComponent.gameObject.name);
            config.WriteJson(writer);
            writer.WriteObjectEnd();

            dataConfigs.Add(JsonMapper.ToObject(writer.ToString()));
        }

        JsonData unityData = new JsonData();

        unityData["value"] = dataConfigs;
        return unityData;
    }

    private static JsonData AddStyleConfig()
    {
        FVSBaseStyle[] styleComponents = GameObject.FindObjectsOfType<FVSBaseStyle>();

        if (styleComponents.Length == 0)
        {
            return null;
        }


        Dictionary<string, List<FVSBaseStyle>> unityConfigData = new Dictionary<string, List<FVSBaseStyle>>();

        foreach (FVSBaseStyle styleComponent in styleComponents)
        {
            styleComponent.LoadConfig();

            var name = styleComponent.gameObject.name;
            if (unityConfigData.ContainsKey(name))
            {
                unityConfigData[name].Add(styleComponent);
            }
            else
            {
                unityConfigData.Add(name, new List<FVSBaseStyle>() { styleComponent });
            }
        }

        JsonData styleConfigs = new JsonData();

        foreach (var keypair in unityConfigData)
        {
            FVSBaseStyle first = keypair.Value[0];
            if (first.configData == null || first.configData == "")
            {
                first.LoadConfig();
            }
            JsonData configData = JsonMapper.ToObject(first.configData);
            styleConfigs.Add(configData);
        }

        JsonData unityStyle = new JsonData();
        unityStyle["value"] = styleConfigs;

        return unityStyle;
    }

    private static void OverwriteLocalizationJson(JsonData configData)
    {
        string path = Path.Combine(Application.streamingAssetsPath, "Localization.json");

        if (!Directory.Exists(Application.streamingAssetsPath))
        {
            Directory.CreateDirectory(Application.streamingAssetsPath);
        }

        // JsonObject更新时，创建或清空JSON文件
        if (File.Exists(path))
        {
            File.WriteAllText(path, "");
        }
        else
        {
            File.Create(path).Dispose();
        }
    
        JsonData localizationData = new JsonData();
        AddLocalizationJsonData(localizationData, configData, "");
        File.WriteAllText(path, localizationData.ToJson());       
    }

    private static void AddLocalizationJsonData(JsonData localizationData, JsonData configData, string displayKey, int index = 0) 
    {
        if (configData == null) return;
        if (configData.IsObject) {
            List<string> keys = new List<string>(configData.Keys);
            foreach (var key in keys) {
                if (key == "displayName") 
                { 
                    string finalDisplayKey = displayKey + index.ToString() + "-" + configData["displayName"].ToString();
                    localizationData[finalDisplayKey] = new JsonData();
                    localizationData[finalDisplayKey]["displayName"] = configData["displayName"].ToString();
                    // configData中添加displayKey
                    configData["displayKey"] = finalDisplayKey;
                }
                else 
                {
                    AddLocalizationJsonData(localizationData, configData[key], displayKey + key.ToString() + "-");
                }
            }
        } 
        else if (configData.IsArray) {
            for (int i = 0; i < configData.Count; i++) {
                AddLocalizationJsonData(localizationData, configData[i], displayKey, i + 1);
            }
        }
    }
}
