// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable disable

using System.Collections.Generic;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Test.Utilities;
using Xunit;

namespace Microsoft.CodeAnalysis.UnitTests.Collections
{
    public class ArrayBuilderTests
    {
        [Fact]
        public void RemoveAll()
        {
            var builder = new ArrayBuilder<int> { 6, 5, 1, 2, 3, 2, 4, 5, 1, 7 };

            builder.RemoveAll((_, _) => false, arg: 0);
            AssertEx.Equal([6, 5, 1, 2, 3, 2, 4, 5, 1, 7], builder);

            builder.RemoveAll((i, arg) => i == arg, arg: 6);
            AssertEx.Equal([5, 1, 2, 3, 2, 4, 5, 1, 7], builder);

            builder.RemoveAll((i, arg) => i == arg, arg: 7);
            AssertEx.Equal([5, 1, 2, 3, 2, 4, 5, 1], builder);

            builder.RemoveAll((i, arg) => i < arg, arg: 3);
            AssertEx.Equal([5, 3, 4, 5], builder);

            builder.RemoveAll((_, _) => true, arg: 0);
            AssertEx.Equal([], builder);

            builder.RemoveAll((_, _) => true, arg: 0);
            AssertEx.Equal([], builder);
        }

        [Fact]
        public void RemoveDuplicates1()
        {
            var builder = new ArrayBuilder<int> { 1, 2, 3, 2, 4, 5, 1 };
            builder.RemoveDuplicates();
            AssertEx.Equal(new[] { 1, 2, 3, 4, 5 }, builder);

            builder = new ArrayBuilder<int> { 1 };
            builder.RemoveDuplicates();
            AssertEx.Equal(new[] { 1 }, builder);

            builder = new ArrayBuilder<int>();
            builder.RemoveDuplicates();
            AssertEx.Equal(new int[0], builder);
        }

        [Fact]
        public void SortAndRemoveDuplicates1()
        {
            var builder = new ArrayBuilder<int> { 5, 1, 3, 2, 4, 1, 2 };
            builder.SortAndRemoveDuplicates(Comparer<int>.Default);
            AssertEx.Equal(new[] { 1, 2, 3, 4, 5 }, builder);

            builder = new ArrayBuilder<int> { 1 };
            builder.SortAndRemoveDuplicates(Comparer<int>.Default);
            AssertEx.Equal(new[] { 1 }, builder);

            builder = new ArrayBuilder<int> { 1, 2 };
            builder.SortAndRemoveDuplicates(Comparer<int>.Default);
            AssertEx.Equal(new[] { 1, 2 }, builder);

            builder = new ArrayBuilder<int> { 1, 2, 3 };
            builder.SortAndRemoveDuplicates(Comparer<int>.Default);
            AssertEx.Equal(new[] { 1, 2, 3 }, builder);

            builder = new ArrayBuilder<int> { 1, 2, 2 };
            builder.SortAndRemoveDuplicates(Comparer<int>.Default);
            AssertEx.Equal(new[] { 1, 2 }, builder);

            builder = new ArrayBuilder<int>();
            builder.SortAndRemoveDuplicates(Comparer<int>.Default);
            AssertEx.Equal(new int[0], builder);
        }

        [Fact]
        public void SelectDistinct1()
        {
            var builder = new ArrayBuilder<int> { 1, 2, 3, 2, 4, 5, 1 };
            AssertEx.Equal(new[] { 1, 2, 3, 4, 5 }, builder.SelectDistinct(n => n));

            builder = new ArrayBuilder<int> { 1 };
            AssertEx.Equal(new[] { 1 }, builder.SelectDistinct(n => n));

            builder = new ArrayBuilder<int>();
            AssertEx.Equal(new int[0], builder.SelectDistinct(n => n));

            builder = new ArrayBuilder<int> { 1, 2, 3, 2, 4, 5, 1 };
            AssertEx.Equal(new[] { 10 }, builder.SelectDistinct(n => 10));

            builder = new ArrayBuilder<int> { 1, 2, 3, 2, 4, 5, 1 };
            AssertEx.Equal(new byte[] { 1, 2, 3, 4, 5 }, builder.SelectDistinct(n => (byte)n));
        }

        [Fact]
        public void AddRange()
        {
            var builder = new ArrayBuilder<int>();

            builder.AddRange(new int[0], 0, 0);
            AssertEx.Equal(new int[0], builder.ToArray());

            builder.AddRange(new[] { 1, 2, 3 }, 0, 3);
            AssertEx.Equal(new[] { 1, 2, 3 }, builder.ToArray());

            builder.AddRange(new[] { 1, 2, 3 }, 2, 0);
            AssertEx.Equal(new[] { 1, 2, 3 }, builder.ToArray());

            builder.AddRange(new[] { 1, 2, 3 }, 1, 1);
            AssertEx.Equal(new[] { 1, 2, 3, 2 }, builder.ToArray());

            builder.AddRange(new[] { 1, 2, 3 }, 1, 2);
            AssertEx.Equal(new[] { 1, 2, 3, 2, 2, 3 }, builder.ToArray());

            builder.AddRange(new[] { 1, 2, 3 }, 2, 1);
            AssertEx.Equal(new[] { 1, 2, 3, 2, 2, 3, 3 }, builder.ToArray());
        }
    }
}
