private void ApplySettings()
        {
            Dictionary <string, object> _remoteDict = new Dictionary <string, object>();

#if UNITY_FIREBASE_REMOTE_CONFIG
            string _remoteValue;
            foreach (var key in FirebaseRemoteConfig.Keys)
            {
                _remoteValue = null;
                _remoteValue = FirebaseRemoteConfig.GetValue(key).StringValue;
                Log(string.Format(" Found Keys : {0} | Value : {1}", key, _remoteValue));
                _remoteDict.Add(key, _remoteValue.StartsWith("[") || _remoteValue.StartsWith("{")? Json.Deserialize(_remoteValue): _remoteValue);
            }
#endif
            if (_remoteDict.Keys.Count > 0)
            {
                string _json = Json.Serialize(_remoteDict);
                Log(string.Format(" Dict Serialized : {0}", _json));
                T _data = new T();
                JsonUtility.FromJsonOverwrite(_json, _data);
                Log(string.Format(" Class Serialized : {0}", JsonUtility.ToJson(_data)));

                if (remoteData != null)
                {
                    remoteData.Dispose();
                }
                remoteData = _data;
            }

            status = Status.SUCCESS;
            OnCompleteCallback?.Invoke(remoteData);
            ResetCallbacks();
        }
        // Start a fetch request.
        private async void FetchDataAsync()
        {
            Task fetchTask =
#if UNITY_FIREBASE_REMOTE_CONFIG
                FirebaseRemoteConfig.FetchAsync(TimeSpan.Zero);
#else
                // emulation of a threading task returning task with some value ( void )
                new Task(delegate { Debug.Log(" Ending waiting ..."); });
#endif
            Log("Start Waiting ...");
            await fetchTask;
            FetchComplete(fetchTask);
        }
        private void FetchComplete(Task fetchTask)
        {
            if (fetchTask.IsCompleted)
            {
                Log("Fetch completed successfully!");
#if UNITY_FIREBASE_REMOTE_CONFIG
                var info = FirebaseRemoteConfig.Info;
                switch (info.LastFetchStatus)
                {
                case LastFetchStatus.Success:
                    FirebaseRemoteConfig.ActivateFetched();
                    Log(string.Format("Remote data loaded and ready (last fetch time {0}).", info.FetchTime));
                    ApplySettings();
                    break;

                case LastFetchStatus.Failure:
                    switch (info.LastFetchFailureReason)
                    {
                    case FetchFailureReason.Error:
                        Log("Fetch failed for unknown reason");
                        status = Status.FAILURE;
                        break;

                    case FetchFailureReason.Throttled:
                        Log("Fetch throttled until " + info.ThrottledEndTime);
                        status = Status.FAILURE;
                        break;
                    }
                    break;

                case LastFetchStatus.Pending:
                    Log("Latest Fetch call still pending.");
                    status = Status.WORKING;
                    break;
                }
#else
                // Emulation
                ApplySettings();
#endif
            }
            else
            {
                Log("Fetch encountered an error.");
                OnErrorCallback?.Invoke((fetchTask.IsCanceled ? "Fetch Canceled! " : "Fetch error! ") + fetchTask.Exception);
            }

            ResetCallbacks();
        }
        private void Init(T defaultData)
        {
            status = Status.WORKING;

#if UNITY_FIREBASE_REMOTE_CONFIG
            if (defaultData == null)
            {
                defaultData = new T();
            }
            FirebaseRemoteConfig.SetDefaults(CovertToDictionary(defaultData));
#endif

            if (Application.internetReachability == NetworkReachability.NotReachable)
            {
                // Offline
                ApplySettings();
            }
            else
            {
                // Online
                FetchDataAsync();
            }
        }