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

namespace JLGames.RocketDriver.Games.RpgMaterial.Common
{
    public static class DataNumUtils
    {
        private static readonly List<DataNum> m_TempNum = new List<DataNum>();

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

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

            return m_TempNum.ToArray();
        }

        /// <summary>
        /// Clean up elements according to filter
        /// 根据filter清理元素
        /// </summary>
        /// <param name="source"></param>
        /// <param name="filter"></param>
        /// <returns></returns>
        public static DataNum[] ClearByFilter(this DataNum[] source, Predicate<DataNum> 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
        /// 清理Num=0的元素
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static DataNum[] ClearByZero(this DataNum[] source)
        {
            return source.ClearByFilter(data => data.Num == 0);
        }

        /// <summary>
        /// Append DataNum data to the array
        /// 追加DataNum数据到数组中
        /// 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 DataNum[] Append(this DataNum[] source, DataNum 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_Num += item.m_Num;
                    return source;
                }
            }

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

        /// <summary>
        /// Append DataNum array elements to the other array
        /// 追加DataNum数组到另一个数组中
        /// 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 DataNum[] Append(this DataNum[] source, DataNum[] 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;
        }

        /// <summary>
        /// Get some elements
        /// 取部分
        /// </summary>
        /// <param name="source"></param>
        /// <param name="match"></param>
        /// <returns></returns>
        public static DataNum[] GetSome(this DataNum[] source, Predicate<DataNum> match)
        {
            if (null == source || source.Length == 0) return source;
            m_TempNum.Clear();
            for (var index = 0; index < source.Length; index++)
            {
                if (match.Invoke(source[index])) m_TempNum.Add(source[index]);
            }

            return m_TempNum.ToArray();
        }

        ///  <summary>
        /// Convert DataNum data to DataOffset data
        /// DataNum => DataOffset
        ///  </summary>
        ///  <param name="num"></param>
        /// <param name="negative"></param>
        /// <returns></returns>
        public static DataOffset ToOffsetData(this DataNum num, bool negative)
        {
            return new DataOffset(num.Type, num.Id, num.UId, negative ? -num.Num : num.Num);
        }

        /// <summary>
        /// Convert DataNum array data to DataOffset array data
        /// DataNum[] => DataOffset[]
        /// </summary>
        /// <param name="nums"></param>
        /// <param name="negative"></param>
        /// <returns></returns>
        public static DataOffset[] ToOffsetData(this DataNum[] nums, bool negative)
        {
            if (nums == null || nums.Length == 0) return null;
            var rs = new DataOffset[nums.Length];
            for (var index = nums.Length - 1; index >= 0; index--)
            {
                rs[index] = nums[index].ToOffsetData(negative);
            }

            return rs;
        }
    }
}