#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#endregion

using System;
using System.Text;
using NUnit.Framework;
using System.IO;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Buffers;
using System.Runtime.InteropServices;
using System.Threading;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;

namespace Google.Protobuf
{
    public class ByteStringTest
    {
        [Test]
        public void Equality()
        {
            ByteString b1 = ByteString.CopyFrom(1, 2, 3);
            ByteString b2 = ByteString.CopyFrom(1, 2, 3);
            ByteString b3 = ByteString.CopyFrom(1, 2, 4);
            ByteString b4 = ByteString.CopyFrom(1, 2, 3, 4);
            EqualityTester.AssertEquality(b1, b1);
            EqualityTester.AssertEquality(b1, b2);
            EqualityTester.AssertInequality(b1, b3);
            EqualityTester.AssertInequality(b1, b4);
            EqualityTester.AssertInequality(b1, null);
            EqualityTester.AssertEquality(ByteString.Empty, ByteString.Empty);
#pragma warning disable 1718 // Deliberately calling ==(b1, b1) and !=(b1, b1)
            Assert.IsTrue(b1 == b1);
            Assert.IsTrue(b1 == b2);
            Assert.IsFalse(b1 == b3);
            Assert.IsFalse(b1 == b4);
            Assert.IsFalse(b1 == null);
            Assert.IsTrue((ByteString) null == null);
            Assert.IsFalse(b1 != b1);
            Assert.IsFalse(b1 != b2);
            Assert.IsTrue(ByteString.Empty == ByteString.Empty);
#pragma warning restore 1718
            Assert.IsTrue(b1 != b3);
            Assert.IsTrue(b1 != b4);
            Assert.IsTrue(b1 != null);
            Assert.IsFalse((ByteString) null != null);
        }

        [Test]
        public void EmptyByteStringHasZeroSize()
        {
            Assert.AreEqual(0, ByteString.Empty.Length);
        }

        [Test]
        public void CopyFromStringWithExplicitEncoding()
        {
            ByteString bs = ByteString.CopyFrom("AB", Encoding.Unicode);
            Assert.AreEqual(4, bs.Length);
            Assert.AreEqual(65, bs[0]);
            Assert.AreEqual(0, bs[1]);
            Assert.AreEqual(66, bs[2]);
            Assert.AreEqual(0, bs[3]);
        }

        [Test]
        public void IsEmptyWhenEmpty()
        {
            Assert.IsTrue(ByteString.CopyFromUtf8("").IsEmpty);
        }

        [Test]
        public void IsEmptyWhenNotEmpty()
        {
            Assert.IsFalse(ByteString.CopyFromUtf8("X").IsEmpty);
        }

        [Test]
        public void CopyFromByteArrayCopiesContents()
        {
            byte[] data = new byte[1];
            data[0] = 10;
            ByteString bs = ByteString.CopyFrom(data);
            Assert.AreEqual(10, bs[0]);
            data[0] = 5;
            Assert.AreEqual(10, bs[0]);
        }

        [Test]
        public void CopyFromReadOnlySpanCopiesContents()
        {
            byte[] data = new byte[1];
            data[0] = 10;
            ReadOnlySpan<byte> byteSpan = data;
            var bs = ByteString.CopyFrom(byteSpan);
            Assert.AreEqual(10, bs[0]);
            data[0] = 5;
            Assert.AreEqual(10, bs[0]);
        }

        [Test]
        public void ToByteArrayCopiesContents()
        {
            ByteString bs = ByteString.CopyFromUtf8("Hello");
            byte[] data = bs.ToByteArray();
            Assert.AreEqual((byte)'H', data[0]);
            Assert.AreEqual((byte)'H', bs[0]);
            data[0] = 0;
            Assert.AreEqual(0, data[0]);
            Assert.AreEqual((byte)'H', bs[0]);
        }

        [Test]
        public void CopyFromUtf8UsesUtf8()
        {
            ByteString bs = ByteString.CopyFromUtf8("\u20ac");
            Assert.AreEqual(3, bs.Length);
            Assert.AreEqual(0xe2, bs[0]);
            Assert.AreEqual(0x82, bs[1]);
            Assert.AreEqual(0xac, bs[2]);
        }

        [Test]
        public void CopyFromPortion()
        {
            byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6};
            ByteString bs = ByteString.CopyFrom(data, 2, 3);
            Assert.AreEqual(3, bs.Length);
            Assert.AreEqual(2, bs[0]);
            Assert.AreEqual(3, bs[1]);
        }

        [Test]
        public void CopyTo()
        {
            byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
            ByteString bs = ByteString.CopyFrom(data);

            byte[] dest = new byte[data.Length];
            bs.CopyTo(dest, 0);

            CollectionAssert.AreEqual(data, dest);
        }

        [Test]
        public void GetEnumerator()
        {
            byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
            ByteString bs = ByteString.CopyFrom(data);

            IEnumerator<byte> genericEnumerator = bs.GetEnumerator();
            Assert.IsTrue(genericEnumerator.MoveNext());
            Assert.AreEqual(0, genericEnumerator.Current);

            IEnumerator enumerator = ((IEnumerable)bs).GetEnumerator();
            Assert.IsTrue(enumerator.MoveNext());
            Assert.AreEqual(0, enumerator.Current);

            // Call via LINQ
            CollectionAssert.AreEqual(bs.Span.ToArray(), bs.ToArray());
        }

        [Test]
        public void UnsafeWrap()
        {
            byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
            ByteString bs = UnsafeByteOperations.UnsafeWrap(data.AsMemory(2, 3));
            ReadOnlySpan<byte> s = bs.Span;

            Assert.AreEqual(3, s.Length);
            Assert.AreEqual(2, s[0]);
            Assert.AreEqual(3, s[1]);
            Assert.AreEqual(4, s[2]);

            // Check that the value is not a copy
            data[2] = byte.MaxValue;
            Assert.AreEqual(byte.MaxValue, s[0]);
        }

        [Test]
        public void CreateCodedInput_FromArraySegment()
        {
            byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
            ByteString bs = UnsafeByteOperations.UnsafeWrap(data.AsMemory(2, 3));
            CodedInputStream codedInputStream = bs.CreateCodedInput();

            byte[] bytes = codedInputStream.ReadRawBytes(3);

            Assert.AreEqual(3, bytes.Length);
            Assert.AreEqual(2, bytes[0]);
            Assert.AreEqual(3, bytes[1]);
            Assert.AreEqual(4, bytes[2]);
            Assert.IsTrue(codedInputStream.IsAtEnd);
        }

        [Test]
        public void WriteToStream()
        {
            byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
            ByteString bs = ByteString.CopyFrom(data);

            MemoryStream ms = new MemoryStream();
            bs.WriteTo(ms);

            CollectionAssert.AreEqual(data, ms.ToArray());
        }

        [Test]
        public void WriteToStream_Stackalloc()
        {
            byte[] data = Encoding.UTF8.GetBytes("Hello world");
            Span<byte> s = stackalloc byte[data.Length];
            data.CopyTo(s);

            MemoryStream ms = new MemoryStream();

            using (UnmanagedMemoryManager<byte> manager = new UnmanagedMemoryManager<byte>(s))
            {
                ByteString bs = ByteString.AttachBytes(manager.Memory);

                bs.WriteTo(ms);
            }

            CollectionAssert.AreEqual(data, ms.ToArray());
        }

        [Test]
        public void ToStringUtf8()
        {
            ByteString bs = ByteString.CopyFromUtf8("\u20ac");
            Assert.AreEqual("\u20ac", bs.ToStringUtf8());
        }

        [Test]
        public void ToStringWithExplicitEncoding()
        {
            ByteString bs = ByteString.CopyFrom("\u20ac", Encoding.Unicode);
            Assert.AreEqual("\u20ac", bs.ToString(Encoding.Unicode));
        }

        [Test]
        public void ToString_Stackalloc()
        {
            byte[] data = Encoding.UTF8.GetBytes("Hello world");
            Span<byte> s = stackalloc byte[data.Length];
            data.CopyTo(s);

            using var manager = new UnmanagedMemoryManager<byte>(s);
            ByteString bs = ByteString.AttachBytes(manager.Memory);
            Assert.AreEqual("Hello world", bs.ToString(Encoding.UTF8));
        }

        [Test]
        public void FromBase64_WithText()
        {
            byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6};
            string base64 = Convert.ToBase64String(data);
            ByteString bs = ByteString.FromBase64(base64);
            Assert.AreEqual(data, bs.ToByteArray());
        }

        [Test]
        public void FromBase64_Empty()
        {
            // Optimization which also fixes issue 61.
            Assert.AreSame(ByteString.Empty, ByteString.FromBase64(""));
        }

        [Test]
        public void ToBase64_Array()
        {
            ByteString bs = ByteString.CopyFrom(Encoding.UTF8.GetBytes("Hello world"));

            Assert.AreEqual("SGVsbG8gd29ybGQ=", bs.ToBase64());
        }

        [Test]
        public void ToBase64_Stackalloc()
        {
            byte[] data = Encoding.UTF8.GetBytes("Hello world");
            Span<byte> s = stackalloc byte[data.Length];
            data.CopyTo(s);

            using var manager = new UnmanagedMemoryManager<byte>(s);
            ByteString bs = ByteString.AttachBytes(manager.Memory);
            Assert.AreEqual("SGVsbG8gd29ybGQ=", bs.ToBase64());
        }

        [Test]
        public void FromStream_Seekable()
        {
            var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
            // Consume the first byte, just to test that it's "from current position"
            stream.ReadByte();
            var actual = ByteString.FromStream(stream);
            ByteString expected = ByteString.CopyFrom(2, 3, 4, 5);
            Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
        }

        [Test]
        public void FromStream_NotSeekable()
        {
            var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
            // Consume the first byte, just to test that it's "from current position"
            stream.ReadByte();
            // Wrap the original stream in LimitedInputStream, which has CanSeek=false
            var limitedStream = new LimitedInputStream(stream, 3);
            var actual = ByteString.FromStream(limitedStream);
            ByteString expected = ByteString.CopyFrom(2, 3, 4);
            Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
        }

        [Test]
        public async Task FromStreamAsync_Seekable()
        {
            var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
            // Consume the first byte, just to test that it's "from current position"
            stream.ReadByte();
            var actual = await ByteString.FromStreamAsync(stream);
            ByteString expected = ByteString.CopyFrom(2, 3, 4, 5);
            Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
        }

        [Test]
        public async Task FromStreamAsync_NotSeekable()
        {
            var stream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 });
            // Consume the first byte, just to test that it's "from current position"
            stream.ReadByte();
            // Wrap the original stream in LimitedInputStream, which has CanSeek=false
            var limitedStream = new LimitedInputStream(stream, 3);
            var actual = await ByteString.FromStreamAsync(limitedStream);
            ByteString expected = ByteString.CopyFrom(2, 3, 4);
            Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
        }

        [Test]
        public void GetHashCode_Regression()
        {
            // We used to have an awful hash algorithm where only the last four
            // bytes were relevant. This is a regression test for
            // https://github.com/protocolbuffers/protobuf/issues/2511

            ByteString b1 = ByteString.CopyFrom(100, 1, 2, 3, 4);
            ByteString b2 = ByteString.CopyFrom(200, 1, 2, 3, 4);
            Assert.AreNotEqual(b1.GetHashCode(), b2.GetHashCode());
        }

        [Test]
        public void GetContentsAsReadOnlySpan()
        {
            var byteString = ByteString.CopyFrom(1, 2, 3, 4, 5);
            var copied = byteString.Span.ToArray();
            CollectionAssert.AreEqual(byteString, copied);
        }

        [Test]
        public void GetContentsAsReadOnlyMemory()
        {
            var byteString = ByteString.CopyFrom(1, 2, 3, 4, 5);
            var copied = byteString.Memory.ToArray();
            CollectionAssert.AreEqual(byteString, copied);
        }

        // Create Memory<byte> from non-array source.
        // Use by ByteString tests that have optimized path for array backed Memory<byte>.
        private sealed unsafe class UnmanagedMemoryManager<T> : MemoryManager<T> where T : unmanaged
        {
            private readonly T* _pointer;
            private readonly int _length;

            public UnmanagedMemoryManager(Span<T> span)
            {
                fixed (T* ptr = &MemoryMarshal.GetReference(span))
                {
                    _pointer = ptr;
                    _length = span.Length;
                }
            }

            public override Span<T> GetSpan() => new Span<T>(_pointer, _length);

            public override MemoryHandle Pin(int elementIndex = 0)
            {
                if (elementIndex < 0 || elementIndex >= _length)
                {
                    throw new ArgumentOutOfRangeException(nameof(elementIndex));
                }

                return new MemoryHandle(_pointer + elementIndex);
            }

            public override void Unpin() { }

            protected override void Dispose(bool disposing) { }
        }
    }
}