﻿using System.Runtime.CompilerServices;

namespace JLGames.RocketDriver.Games.RpgMaterial.Common
{
    public struct DataOffset
    {
        internal readonly int m_Type;
        internal readonly int m_Id;
        internal readonly int m_UId;
        internal int m_Offset;

        /// <summary>
        /// Type
        /// 类型
        /// </summary>
        public int Type => m_Type;

        /// <summary>
        /// Id
        /// </summary>
        public int Id => m_Id;

        /// <summary>
        /// UId
        /// </summary>
        public int UId => m_UId;

        /// <summary>
        /// Offset
        /// 偏移值
        /// </summary>
        public int Offset => m_Offset;

        /// <summary>
        /// Absolute value of offset
        /// 偏移绝对值
        /// </summary>
        public int AbsOffset => m_Offset < 0 ? -m_Offset : m_Offset;

        /// <summary>
        /// Check for empty data
        /// 检测是否为空数据
        /// </summary>
        public bool IsNone => m_Id == 0 || m_Type == 0 || m_Offset == 0;

        public override string ToString()
        {
            return $"Offset{{Type={Type},Id={Id},UId={UId},Offset={Offset}}}";
        }

        public DataOffset(int type, int id, int uId, int offset)
        {
            m_Type = type;
            m_Id = id;
            m_UId = uId;
            m_Offset = offset;
        }

        /// <summary>
        /// Addition
        /// DataOffset + int
        /// </summary>
        /// <param name="b">DataOffset</param>
        /// <param name="num">数量</param>
        /// <returns></returns>
        [MethodImpl((MethodImplOptions) 256)]
        public static DataOffset operator +(DataOffset b, int num)
        {
            return new DataOffset(b.Type, b.Id, b.UId, b.Offset + num);
        }

        /// <summary>
        /// Subtraction
        /// DataOffset - int
        /// </summary>
        /// <param name="b">DataOffset</param>
        /// <param name="num">数量</param>
        /// <returns></returns>
        [MethodImpl((MethodImplOptions) 256)]
        public static DataOffset operator -(DataOffset b, int num)
        {
            return b + -num;
        }

        /// <summary>
        /// Negative
        /// DataOffset中Offset求负
        /// </summary>
        /// <param name="b">DataOffset</param>
        /// <returns></returns>
        [MethodImpl((MethodImplOptions) 256)]
        public static DataOffset operator -(DataOffset b)
        {
            return new DataOffset(b.Type, b.Id, b.UId, -b.Offset);
        }

        /// <summary>
        /// Multiplication
        /// DataOffset中Offset求积
        /// </summary>
        /// <param name="b">DataOffset</param>
        /// <param name="num">倍数</param>
        /// <returns></returns>
        [MethodImpl((MethodImplOptions) 256)]
        public static DataOffset operator *(DataOffset b, int num)
        {
            return new DataOffset(b.Type, b.Id, b.UId, b.Offset * num);
        }

        // static

        private const char SepField = ':';
        private const char SepEntity = '&';
        private static readonly DataOffset m_None = new DataOffset();

        public static DataOffset FromString(string content, char sepField = SepField)
        {
            if (string.IsNullOrEmpty(content)) return m_None;
            var ss = content.Split(sepField);
            var type = int.Parse(ss[0]);
            var id = int.Parse(ss[1]);
            var val = int.Parse(ss[2]);
            if (ss.Length == 3)
            {
                return new DataOffset(type, id, 0, val);
            }

            return new DataOffset(type, id, val, int.Parse(ss[3]));
        }

        public static DataOffset[] ArrayFromString(string content, char sepEntity = SepEntity,
            char sepField = SepField)
        {
            if (string.IsNullOrEmpty(content)) return null;
            var cs = content.Split(sepEntity);
            if (cs.Length == 0) return null;
            var rs = new DataOffset[cs.Length];
            for (var index = 0; index < cs.Length; index++)
            {
                rs[index] = FromString(cs[index], sepField);
            }

            return rs;
        }
    }
}