﻿using System;
using System.Collections.Generic;
using UnityEngine;

namespace JLGames.RocketDriver.Games.LocalAccount
{
    [Serializable]
    public sealed class LocalAccountDatabase<T> where T : LocalAccount
    {
        [SerializeField] private string m_LoggingId;
        [SerializeField] private T[] m_Accounts;

        private readonly List<T> m_AccountList = new List<T>();

        public string LoggingId => m_LoggingId;
        public T LoggingAccount => string.IsNullOrEmpty(m_LoggingId) ? null : FindAccountById(m_LoggingId);
        public bool ExistLogging => !string.IsNullOrEmpty(m_LoggingId);
        /// <summary>
        /// Guest information
        /// 游客信息
        /// The UserName of the guest is empty
        /// 游客的UserName为空
        /// </summary>
        public T Guest => FindAccountByName("");

        public bool CheckExistById(string userId)
        {
            return null != FindAccountById(userId);
        }

        public bool CheckExistByName(string userName)
        {
            return null != FindAccountByName(userName);
        }

        public bool CheckLogging(string userName)
        {
            return ExistLogging && FindAccountById(m_LoggingId).UserName == userName;
        }

        public T FindAccountById(string userId)
        {
            return m_AccountList.Find(account => account.UserId == userId);
        }

        public T FindAccountByName(string userName)
        {
            return m_AccountList.Find(account => account.UserName == userName);
        }

        public string SignOut()
        {
            if (string.IsNullOrEmpty(m_LoggingId)) return null;
            var rs = m_LoggingId;
            m_LoggingId = null;
            return rs;
        }

        public bool SignIn(string userId)
        {
            if (!CheckExistById(userId)) return false;
            m_LoggingId = userId;
            FindAccountById(userId).UpdateLoginTime();
            return true;
        }

        public bool Add(T account)
        {
            if (null == account || CheckExistById(account.UserId) || CheckExistByName(account.UserName)) return false;
            m_AccountList.Add(account);
            return true;
        }

        //------------------------

        private void SortAccounts()
        {
            m_AccountList.Sort((account1, account2) => account2.LoginTime.CompareTo(account1.LoginTime));
        }

        private void Array2List()
        {
            m_AccountList.Clear();
            m_AccountList.AddRange(m_Accounts);
        }

        private void List2Array()
        {
            SortAccounts();
            m_Accounts = m_AccountList.ToArray();
        }

        public string ToJson()
        {
            List2Array();
            return JsonUtility.ToJson(this);
        }

        public void FroamJosnOverride(string json)
        {
            JsonUtility.FromJsonOverwrite(json, this);
            Array2List();
        }
    }
}