using System;
using System.Collections.Generic;

using ExtensionMethods;

using Xunit;

namespace ExtensionsTests {
  public class IEquatableExtensionsTests {

    private class DummyClass : IEquatable<DummyClass> {
      public string? Test { get; set; }

      public bool Equals(DummyClass? other) {
        if (other == null)
          return false;

        return other.Test == Test;
      }

      public override int GetHashCode() {
        unchecked {
          int hash = 17;

          if (Test != null)
            hash = hash * 23 + Test.GetHashCode();
          
          return hash;
        }
      }
    }


    [Fact]
    public void Eq() {
      Assert.True(
        !new DummyClass { Test = "test" }.Eq(new DummyClass { Test = "Test" })
        && new DummyClass { Test = "Test" }.Eq(new DummyClass { Test = "Test" })
        && !new DummyClass().Eq(new DummyClass { Test = "Test" })
      );
    }

    [Fact]
    public void EnumerableEq() {

      var emptyList = new List<DummyClass>();

      var list1 = new List<DummyClass> {
      new DummyClass {
        Test = "12345"
      },
      new DummyClass {
        Test = "67890"
      }
    };

      var list2 = new List<DummyClass> {
      new DummyClass {
        Test = "67890"
      },
      new DummyClass {
        Test = "12345"
      }
    };

      var list3 = new List<DummyClass> {
      new DummyClass {
        Test = "12345"
      },
      new DummyClass {
        Test = "ABCDE"
      }
    };

      var list4 = new List<DummyClass> {
      new DummyClass {
        Test = "12345"
      },
      new DummyClass {
        Test = "67890"
      },
      new DummyClass {
        Test = "67890"
      }
    };

      var list5 = new List<DummyClass> {
      new DummyClass {
        Test = "12345"
      },
      new DummyClass {
        Test = "12345"
      },
      new DummyClass {
        Test = "67890"
      }
    };


      // compare between two empty lists (true)
      var result1 = emptyList.EnumerableEq(emptyList);

      // compare between empty and full list (false)
      var result2 = emptyList.EnumerableEq(list1);

      // compare between same but unordered lists (true)
      var result3 = list1.EnumerableEq(list2);

      // compare beween two different lists of the same lenght (false)
      var result4 = list1.EnumerableEq(list3);

      // compare between two different lenght lists containing same elements (false)
      var result5 = list1.EnumerableEq(list4);

      // compare between different lists with same lenght and same elements but different proportions (false)
      var result6 = list4.EnumerableEq(list5);

      Assert.True(
        result1
        && !result2
        && result3
        && !result4
        && !result5
        && !result6
      );
    }
  }
}
