#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#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) { }
        }
    }
}