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

namespace JLGames.RocketDriver.Actions.Localx
{
    public class DomainManager
    {
        private string m_DomainKey = LocalKeys.DomainKey;
        private string m_ListKey = LocalKeys.DomainListKey;
        private char m_ListSeparator = LocalKeys.Separator;

        private string m_Domain;
        private readonly List<string> m_DomainList = new List<string>();
        private bool m_Inited;

        /// <summary>
        /// Whether the initialization has been completed
        /// 是否已经完成初始化
        /// </summary>
        public bool Inited => m_Inited;

        /// <summary>
        /// Current domain
        /// 当前域名值
        /// </summary>
        public string CurrentDomain => m_Domain;

        /// <summary>
        /// Whether the current domain is online (whether the value has been set)
        /// 当前域名是否在线(是否已经设置值)
        /// </summary>
        public bool DomainOnline => !DomainOffline;

        /// <summary>
        /// Whether the current domain is offline
        /// 当前域名是否离线
        /// </summary>
        public bool DomainOffline => string.IsNullOrEmpty(m_Domain);

        /// <summary>
        /// Values of domain list
        /// 域名值列表
        /// </summary>
        public string[] DomainList => m_DomainList.ToArray();

        /// <summary>
        /// First value of domain list
        /// 列表第一个账号
        /// </summary>
        public string FirstDomain => m_DomainList?[0];

        /// <summary>
        /// Size of domain list
        /// 域名列表数量
        /// </summary>
        public int DomainSize => m_DomainList.Count;

        /// <summary>
        /// Init
        /// 初始化
        /// </summary>
        /// <param name="domainKey"></param>
        /// <param name="listKey"></param>
        /// <param name="listSeparator"></param>
        public void Init(string domainKey, string listKey, char listSeparator)
        {
            m_DomainKey = domainKey;
            m_ListKey = listKey;
            m_ListSeparator = listSeparator;
            DomainFromPlayerPrefs();
            ListFromPlayerPrefs();
            m_Inited = true;
        }

        /// <summary>
        /// Set the current domain value
        /// 设置当前域名值
        /// The new domain name will be automatically added to the list
        /// 新域名会自动加入到列表中
        /// </summary>
        /// <param name="domain"></param>
        public bool SetDomain(string domain)
        {
            if (string.IsNullOrEmpty(domain))
            {
                return false;
            }

            if (!CheckDomainInList(domain))
            {
                InsertDomain(domain);
            }

            if (m_Domain == domain) return false;
            return SwitchDomain(domain);
        }

        /// <summary>
        /// Insert the domain to the top of the domain list
        /// 插入域名到域名列表首位
        /// </summary>
        /// <param name="domain"></param>
        /// <returns>false:domain verification failed | already in the list(domain验证不通过|已经在列表中)</returns>
        public bool InsertDomain(string domain)
        {
            if (string.IsNullOrEmpty(domain) || CheckDomainInList(domain)) return false;
            m_DomainList.Insert(0, domain);
            ListToPlayerPrefs();
            return true;
        }

        /// <summary>
        /// Switch the current domain
        /// 切换当前域名
        /// Prerequisite: domain in the domain list
        /// 前提：域名处理列表中
        /// </summary>
        /// <param name="domain"></param>
        /// <returns>false:验证不通过|不在列表中|当前账号在线</returns>
        public bool SwitchDomain(string domain)
        {
//            DebugUtil.Log("SwitchDomain:", domain, m_Domain);
            if (string.IsNullOrEmpty(domain) || !CheckDomainInList(domain)) return false;
            if (m_Domain == domain) return false;

            m_Domain = domain;
            DomainToPlayerPrefs();
            var index = m_DomainList.IndexOf(domain);
            if (0 != index)
            {
                m_DomainList.RemoveAt(index);
                m_DomainList.Insert(0, domain);
            }

            return true;
        }

        /// <summary>
        /// Clear the value of the current domain
        /// 清除当前域名设置的值
        /// </summary>
        public void ClearDomain()
        {
            m_Domain = "";
            DomainToPlayerPrefs();
        }

        /// <summary>
        /// Find domain
        /// 查找域名
        /// </summary>
        /// <param name="match"></param>
        /// <returns></returns>
        public string FindDomain(Predicate<string> match)
        {
            return m_DomainList.Find(match);
        }

        /// <summary>
        /// Add domain to the end of the list
        /// 添加域名到列表尾部
        /// </summary>
        /// <param name="domain"></param>
        public void AddDomainToList(string domain)
        {
            if (CheckDomainInList(domain)) return;
            m_DomainList.Add(domain);
            ListToPlayerPrefs();
        }

        /// <summary>
        /// Add domains to the end of the list
        /// 添加域名到列表
        /// </summary>
        /// <param name="domain"></param>
        public void AddDomainToList(string[] domain)
        {
            if (null == domain || domain.Length == 0) return;
            foreach (var o in domain)
            {
                if (CheckDomainInList(o)) continue;
                m_DomainList.Add(o);
            }

            ListToPlayerPrefs();
        }

        /// <summary>
        /// Add domains to the end of the list
        /// 添加域名到列表
        /// </summary>
        /// <param name="domain"></param>
        public void AddDomainToList(IEnumerable<string> domain)
        {
            if (null == domain) return;
            foreach (var o in domain)
            {
                if (CheckDomainInList(o)) continue;
                m_DomainList.Add(o);
            }

            ListToPlayerPrefs();
        }

        /// <summary>
        /// Add the domain value to the specified location in the list
        /// 添加域名值到列表中的指定位置
        /// </summary>
        /// <param name="domain"></param>
        /// <param name="index"></param>
        public void AddDomainToList(string domain, int index)
        {
            if (CheckDomainInList(domain)) return;
            m_DomainList.Insert(index, domain);
            ListToPlayerPrefs();
        }

        /// <summary>
        /// Add the domains to the specified location in the list
        /// 添加多个域名值到列表中的指定位置
        /// </summary>
        /// <param name="domain"></param>
        /// <param name="index"></param>
        public void AddDomainToList(string[] domain, int index)
        {
            if (null == domain || domain.Length == 0) return;
            var add = 0;
            foreach (var o in domain)
            {
                if (CheckDomainInList(o)) continue;
                m_DomainList.Insert(add + index, o);
                add += 1;
            }

            ListToPlayerPrefs();
        }

        /// <summary>
        /// Add the domains to the specified location in the list
        /// 添加多个域名值到列表中的指定位置
        /// </summary>
        /// <param name="domain"></param>
        /// <param name="index"></param>
        public void AddDomainToList(IEnumerable<string> domain, int index)
        {
            if (null == domain) return;
            var add = 0;
            foreach (var o in domain)
            {
                if (CheckDomainInList(o)) continue;
                m_DomainList.Insert(add + index, o);
                add += 1;
            }

            ListToPlayerPrefs();
        }

        /// <summary>
        /// Remove a domain from the list
        /// 从列表中删除域名
        /// </summary>
        /// <param name="domain"></param>
        public void RemoveDomainFromList(string domain)
        {
            if (!CheckDomainInList(domain)) return;
            m_DomainList.Remove(domain);
            ListToPlayerPrefs();
        }

        /// <summary>
        /// Remove domains from the list
        /// 从列表中删除域名
        /// </summary>
        /// <param name="domain"></param>
        public void RemoveDomainFromList(string[] domain)
        {
            if (null == domain || domain.Length == 0) return;
            foreach (var o in domain)
            {
                if (!CheckDomainInList(o)) return;
                m_DomainList.Remove(o);
            }

            ListToPlayerPrefs();
        }

        /// <summary>
        /// Remove a domains from the list
        /// 从列表中删除域名
        /// </summary>
        /// <param name="domain"></param>
        public void RemoveDomainFromList(IEnumerable<string> domain)
        {
            if (null == domain) return;
            foreach (var o in domain)
            {
                if (!CheckDomainInList(o)) return;
                m_DomainList.Remove(o);
            }

            ListToPlayerPrefs();
        }

        /// <summary>
        /// Clear the domain list
        /// 清空域名列表
        /// </summary>
        public void ClearDomainList()
        {
            if (m_DomainList.Count == 0) return;
            m_DomainList.Clear();
            ListToPlayerPrefs();
        }

        /// <summary>
        /// Check if the domain is in the list
        /// 检查域名是否在列表中
        /// </summary>
        /// <param name="domain"></param>
        /// <returns></returns>
        public bool CheckDomainInList(string domain)
        {
            if (string.IsNullOrEmpty(domain)) return false;
            if (m_DomainList.Count == 0) return false;
            return m_DomainList.Contains(domain);
        }

        private void DomainToPlayerPrefs()
        {
            PlayerPrefs.SetString(m_DomainKey, m_Domain);
        }

        private void DomainFromPlayerPrefs()
        {
            m_Domain = PlayerPrefs.GetString(m_DomainKey);
        }

        private void ListFromPlayerPrefs()
        {
            var list = PlayerPrefs.GetString(m_ListKey);
            m_DomainList.Clear();
            if (string.IsNullOrEmpty(list)) return;
            var arr = list.Split(',');
            if (arr.Length == 0) return;
            m_DomainList.AddRange(arr);
        }

        private void ListToPlayerPrefs()
        {
            var list = "";
            if (m_DomainList.Count > 0)
            {
                list = string.Join(m_ListSeparator.ToString(), m_DomainList);
            }

            PlayerPrefs.SetString(m_ListKey, list);
        }
    }
}