﻿using System;
using System.Collections.Generic;
using JLGames.RocketDriver.CSharp.Utils;

namespace JLGames.RocketDriver.Games.RpgMaterial.Common
{
    public static class UserNotifyDataUtils
    {
        private static readonly List<UserNotifyData> m_TempData = new List<UserNotifyData>();

        /// <summary>
        /// Merge elements with the same Id and Type
        /// 合并Id与Type相同的元素
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static UserNotifyData[] Merged(this UserNotifyData[] source)
        {
            if (null == source) return null;
            if (source.Length <= 1) return source;

            m_TempData.Clear();
            m_TempData.AddRange(source);
            for (var lastIndex = m_TempData.Count - 1; lastIndex >= 0; lastIndex--)
            {
                var last = m_TempData[lastIndex];
                for (var firstIndex = 0; firstIndex < lastIndex; firstIndex++)
                {
                    var first = m_TempData[firstIndex];
                    if (first.Type == last.Type && first.Id == last.Id)
                    {
                        first.m_Num += last.m_Num;
                        first.m_Offset += last.m_Offset;
                        m_TempData[firstIndex] = first;
                        m_TempData.RemoveAt(lastIndex);
                        break;
                    }
                }
            }

            return m_TempData.ToArray();
        }

        /// <summary>
        /// Clean up elements according to filter
        /// 清理
        /// </summary>
        /// <param name="source"></param>
        /// <param name="filter"></param>
        /// <returns></returns>
        public static UserNotifyData[] ClearByFilter(this UserNotifyData[] source, Predicate<UserNotifyData> filter)
        {
            if (null == source) return null;
            if (source.Length == 0) return source;
            for (var index = source.Length - 1; index >= 0; index--)
            {
                if (filter.Invoke(source[index]))
                {
                    source = ArrayUtil.RemoveElement(source, index, 1);
                }
            }

            return source;
        }

        /// <summary>
        /// Clean up elements with Num=0 and Offset=0
        /// Num==0 && Offset==0
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static UserNotifyData[] ClearByZero(this UserNotifyData[] source)
        {
            return source.ClearByFilter(data => data.Num == 0 && data.Offset == 0);
        }

        /// <summary>
        /// Append UserNotifyData data to the array
        /// 追加UserNotifyData数据到数组中
        /// The same Type and Id can use merged data
        /// 相同Type和Id可使用合并数据
        /// </summary>
        /// <param name="source"></param>
        /// <param name="item"></param>
        /// <param name="mergeToSource">合并到原始</param>
        /// <returns></returns>
        public static UserNotifyData[] Append(this UserNotifyData[] source, UserNotifyData item, bool mergeToSource = false)
        {
            if (null == source || source.Length == 0) return new[] {item};

            if (mergeToSource)
            {
                var index = Array.FindIndex(source, offset => offset.Id == item.Id && offset.Type == item.Type);
                if (index >= 0)
                {
                    source[index].m_Offset += item.m_Offset;
                    source[index].m_Num += item.m_Num;
                    return source;
                }
            }

            var rs = new UserNotifyData[source.Length + 1];
            Array.Copy(source, rs, source.Length);
            rs[rs.Length - 1] = item;
            return rs;
        }

        /// <summary>
        /// Append UserNotifyData array elements to the other array
        /// 追加UserNotifyData数组到另一个数组中
        /// The same Type and Id can use merged data
        /// 相同Type和Id可使用合并数据
        /// </summary>
        /// <param name="source"></param>
        /// <param name="items"></param>
        /// <param name="mergeToSource">合并到原始</param>
        /// <returns></returns>
        public static UserNotifyData[] Append(this UserNotifyData[] source, UserNotifyData[] items, bool mergeToSource = false)
        {
            if (null == items || items.Length == 0) return source;

            var rs = source;
            foreach (var item in items)
            {
                rs = Append(rs, item, mergeToSource);
            }

            return rs;
        }
    }
}