using JT1078.Protocol.Buffers;
using System;
using System.Buffers;
using System.Buffers.Binary;

namespace JT1078.Protocol.MessagePack
{
    ref struct JT1078MessagePackWriter
    {
        private JT1078BufferWriter writer;
        public JT1078MessagePackWriter(Span<byte> buffer)
        {
            this.writer = new JT1078BufferWriter(buffer);
        }
        public byte[] FlushAndGetArray()
        {
            return writer.Written.ToArray();
        }
        public void WriteByte(byte value)
        {
            var span = writer.Free;
            span[0] = value;
            writer.Advance(1);
        }
        public void WriteUInt16(ushort value)
        {
            var span = writer.Free;
            span[0] = (byte)(value >> 8);
            span[1] = (byte)value;
            writer.Advance(2);
        }
        public void WriteInt32(int value)
        {
            var span = writer.Free;
            span[0] = (byte)(value >> 24);
            span[1] = (byte)(value >> 16);
            span[2] = (byte)(value >> 8);
            span[3] = (byte)value;
            writer.Advance(4);
        }
        public void WriteUInt64(ulong value)
        {
            var span = writer.Free;
            span[0] = (byte)(value >> 56);
            span[1] = (byte)(value >> 48);
            span[2] = (byte)(value >> 40);
            span[3] = (byte)(value >> 32);
            span[4] = (byte)(value >> 24);
            span[5] = (byte)(value >> 16);
            span[6] = (byte)(value >> 8);
            span[7] = (byte)value;
            writer.Advance(8);
        }
        public void WriteUInt32(uint value)
        {
            var span = writer.Free;
            span[0] = (byte)(value >> 24);
            span[1] = (byte)(value >> 16);
            span[2] = (byte)(value >> 8);
            span[3] = (byte)value;
            writer.Advance(4);
        }
        public void WriteArray(ReadOnlySpan<byte> src)
        {
            src.CopyTo(writer.Free);
            writer.Advance(src.Length);
        }
        public void WriteBCD(string value, int len)
        {
            string bcdText = value ?? "";
            int startIndex = 0;
            int noOfZero = len - bcdText.Length;
            if (noOfZero > 0)
            {
                bcdText = bcdText.Insert(startIndex, new string('0', noOfZero));
            }
            int byteIndex = 0;
            int count = len / 2;
            var bcdSpan = bcdText.AsSpan();
            var spanFree = writer.Free;
            while (startIndex < bcdText.Length && byteIndex < count)
            {
                spanFree[byteIndex++] = Convert.ToByte(bcdSpan.Slice(startIndex, 2).ToString(), 16);
                startIndex += 2;
            }
            writer.Advance(byteIndex);
        }
        /// <summary>
        /// 数字编码 大端模式、高位在前
        /// </summary>
        /// <param name="value"></param>
        /// <param name="len"></param>
        public void WriteBigNumber(string value, int len)
        {
            var spanFree = writer.Free;
            ulong number = string.IsNullOrEmpty(value) ? 0 : (ulong)double.Parse(value);
            for (int i = len - 1; i >= 0; i--)
            {
                spanFree[i] = (byte)(number & 0xFF);  //取低8位
                number = number >> 8;
            }
            writer.Advance(len);
        }
        public int GetCurrentPosition()
        {
            return writer.WrittenCount;
        }
    }
}
