using System;
using UnityEngine;

namespace UVC.Json
{
    /// <summary>
    /// JsonUtility를 이용한 배열 직렬화/역직렬화
    /// Unity의 기본 JsonUtility는 최상위 배열을 지원하지 않기 때문에 Wrapper 클래스를 사용하여 이 문제를 해결합니다.
    /// 참조: https://stackoverflow.com/questions/36239705/serialize-and-deserialize-json-and-json-array-in-unity
    /// </summary>
    public static class JsonUtilityHelper
    {
        /// <summary>
        /// JSON 문자열을 T 타입 배열로 역직렬화합니다.
        /// </summary>
        /// <typeparam name="T">배열 요소의 타입</typeparam>
        /// <param name="json">역직렬화할 JSON 문자열</param>
        /// <returns>역직렬화된 T 타입 배열</returns>
        /// <example>
        /// <code>
        /// // Player 클래스가 [Serializable] 속성을 가지고 있다고 가정
        /// string jsonData = "{\"Items\":[{\"name\":\"플레이어1\",\"level\":10},{\"name\":\"플레이어2\",\"level\":20}]}";
        /// Player[] players = JsonUtilityHelper.FromJson<Player>(jsonData);
        /// // players[0].name == "플레이어1", players[0].level == 10
        /// // players[1].name == "플레이어2", players[1].level == 20
        /// </code>
        /// </example>
        public static T[] FromJson<T>(string json)
        {
            Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>>(json);
            return wrapper.Items;
        }

        /// <summary>
        /// T 타입 배열을 JSON 문자열로 직렬화합니다.
        /// </summary>
        /// <typeparam name="T">배열 요소의 타입</typeparam>
        /// <param name="array">직렬화할 배열</param>
        /// <returns>직렬화된 JSON 문자열</returns>
        /// <example>
        /// <code>
        /// // Player 클래스가 [Serializable] 속성을 가지고 있다고 가정
        /// Player[] players = new Player[]
        /// {
        ///     new Player { name = "플레이어1", level = 10 },
        ///     new Player { name = "플레이어2", level = 20 }
        /// };
        /// 
        /// string json = JsonUtilityHelper.ToJson(players);
        /// // json == "{\"Items\":[{\"name\":\"플레이어1\",\"level\":10},{\"name\":\"플레이어2\",\"level\":20}]}"
        /// </code>
        /// </example>
        public static string ToJson<T>(T[] array)
        {
            Wrapper<T> wrapper = new Wrapper<T>();
            wrapper.Items = array;
            return JsonUtility.ToJson(wrapper);
        }

        /// <summary>
        /// T 타입 배열을 JSON 문자열로 직렬화합니다. 가독성 향상을 위한 들여쓰기 옵션을 제공합니다.
        /// </summary>
        /// <typeparam name="T">배열 요소의 타입</typeparam>
        /// <param name="array">직렬화할 배열</param>
        /// <param name="prettyPrint">들여쓰기를 포함한 가독성 높은 형식 사용 여부</param>
        /// <returns>직렬화된 JSON 문자열</returns>
        /// <example>
        /// <code>
        /// // Player 클래스가 [Serializable] 속성을 가지고 있다고 가정
        /// Player[] players = new Player[]
        /// {
        ///     new Player { name = "플레이어1", level = 10 },
        ///     new Player { name = "플레이어2", level = 20 }
        /// };
        /// 
        /// string json = JsonUtilityHelper.ToJson(players, true);
        /// // json은 다음과 같이 들여쓰기가 포함된 형식:
        /// // {
        /// //   "Items": [
        /// //     {
        /// //       "name": "플레이어1",
        /// //       "level": 10
        /// //     },
        /// //     {
        /// //       "name": "플레이어2",
        /// //       "level": 20
        /// //     }
        /// //   ]
        /// // }
        /// </code>
        /// </example>
        public static string ToJson<T>(T[] array, bool prettyPrint)
        {
            Wrapper<T> wrapper = new Wrapper<T>();
            wrapper.Items = array;
            return JsonUtility.ToJson(wrapper, prettyPrint);
        }

        /// <summary>
        /// 배열을 위한 직렬화 래퍼 클래스입니다.
        /// Unity의 JsonUtility는 최상위 배열을 직접 지원하지 않기 때문에 이 클래스로 배열을 감싸줍니다.
        /// </summary>
        /// <typeparam name="T">배열 요소의 타입</typeparam>
        [Serializable]
        private class Wrapper<T>
        {
            public T[] Items;
        }
    }

}
