<commit_before>﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using FlyTrace.LocationLib;
using FlyTrace.LocationLib.Data;
using FlyTrace.LocationLib.ForeignAccess.Spot;
using Xunit;
using Xunit.Abstractions;

namespace LocationLib.Test
{
  public class SpotFeedRequestTests
  {
    private readonly ITestOutputHelper _output;

    public SpotFeedRequestTests(ITestOutputHelper output)
    {
      _output = output;
    }

    [Theory]
    [InlineData(true)]
    [InlineData(false)]
    public void BasicTest(bool squeezeXml)
    {
      _output.WriteLine("squeezeXml: " + squeezeXml);
      TrackerState trackerState = Req("BasicRequest.xml", squeezeXml);

      Assert.Null(trackerState.Error);
      Assert.Equal(2, trackerState.Position.FullTrack.Length);

      Assert.Equal("OK", trackerState.Position.CurrPoint.LocationType);
      Assert.Equal(1, trackerState.Position.CurrPoint.Latitude);
      Assert.Equal(2, trackerState.Position.CurrPoint.Longitude);

      Assert.Equal("TRACK", trackerState.Position.PreviousPoint.LocationType);
      Assert.Equal(3, trackerState.Position.PreviousPoint.Latitude);
      Assert.Equal(4, trackerState.Position.PreviousPoint.Longitude);

      Assert.True(ReferenceEquals(trackerState.Position.CurrPoint, trackerState.Position.FullTrack[0]));
      Assert.True(ReferenceEquals(trackerState.Position.PreviousPoint, trackerState.Position.FullTrack[1]));

      Assert.True(trackerState.Position.CurrPoint.ForeignTime > trackerState.Position.PreviousPoint.ForeignTime);
    }

    [Theory]
    [InlineData(true)]
    [InlineData(false)]
    public void CombinationsTest(bool squeezeXml)
    {
      _output.WriteLine("squeezeXml: " + squeezeXml);

      const string resourceName = "Combinations.xml";
      string xml = GetResourceAsString(resourceName);
      XDocument doc = XDocument.Load(new StringReader(xml));
      IEnumerable<XElement> messageElements = doc.XPathSelectElements("/response/feedMessageResponse/messages/message");
      int messagesCount = messageElements.Count();

      TrackerState trackerState = Req(resourceName, squeezeXml);

      Assert.Null(trackerState.Error);

      // Some of the elements are intentionally not valid in the test XML:
      Assert.Equal(messagesCount - 4, trackerState.Position.FullTrack.Length);

      DateTime? time = null;
      for (var iMessage = 0; iMessage < trackerState.Position.FullTrack.Length; iMessage++)
      {
        TrackPointData pointData = trackerState.Position.FullTrack[iMessage];
        try
        {
          if (time == null)
          {
            time = pointData.ForeignTime;
          }

          double latitude = pointData.Latitude;
          Assert.True((int)latitude == 1 || (int)latitude == 2 || (int)latitude == 11 || (int)latitude == 12);

          double longitude = pointData.Longitude;
          Assert.True((int)longitude == 20 || (int)longitude == 21);

          Assert.Equal(DateTimeKind.Utc, pointData.ForeignTime.Kind);
          Assert.Equal(time, pointData.ForeignTime);

          bool shouldHaveMessage = (int)latitude == 1 || (int)latitude == 11;
          bool shouldHaveAltitude = (int)latitude == 11 || (int)latitude == 12;
          bool isOk = (int)longitude == 20;
          bool isTrack = (int)longitude == 21;

          time = time.Value.AddMinutes(-10);

          if (shouldHaveAltitude)
            Assert.Equal(123, pointData.Altitude);
          else
            Assert.Null(pointData.Altitude);

          if (isTrack)
            Assert.Equal("TRACK", pointData.LocationType);

          if (isOk)
            Assert.Equal("OK", pointData.LocationType);

          if (shouldHaveMessage)
            Assert.Equal("Need beer and retrieve", pointData.UserMessage);
          else
            Assert.Null(pointData.UserMessage);
        }
        catch
        {
          _output.WriteLine($"Problem with message #{iMessage}");
          throw;
        }
      }
    }

    private static TrackerState Req(string resourceName, bool squeezeXml)
    {
      string xml = ProcessTestXml(resourceName, squeezeXml);
      var request = new SpotFeedRequest("test", xml, 1);

      TrackerState result = null;

      request.BeginRequest(asyncResult =>
      {
        result = request.EndRequest(asyncResult);
      }, null);

      Assert.NotNull(result);

      return result;
    }

    private static string GetResourceAsString(string resourceName)
    {
      Assembly assembly = Assembly.GetExecutingAssembly();

      using (Stream stream = assembly.GetManifestResourceStream("LocationLib.Test." + resourceName))
      {
        if (stream == null)
          throw new FileNotFoundException($"Cannot find resource '{resourceName}'");

        using (StreamReader reader = new StreamReader(stream))
        {
          return reader.ReadToEnd();
        }
      }
    }

    [Fact]
    public void ReplaceTestXml()
    {
      _output.WriteLine(ProcessTestXml("Combinations.xml", true));
    }


    // Utility method to make date-time in test XML going backwards properly with each message
    private static string ProcessTestXml(string resourceName, bool squeezeXml)
    {<commit_msg>Skip utility unit test<commit_after>﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using FlyTrace.LocationLib;
using FlyTrace.LocationLib.Data;
using FlyTrace.LocationLib.ForeignAccess.Spot;
using Xunit;
using Xunit.Abstractions;

namespace LocationLib.Test
{
  public class SpotFeedRequestTests
  {
    private readonly ITestOutputHelper _output;

    public SpotFeedRequestTests(ITestOutputHelper output)
    {
      _output = output;
    }

    [Theory]
    [InlineData(true)]
    [InlineData(false)]
    public void BasicTest(bool squeezeXml)
    {
      _output.WriteLine("squeezeXml: " + squeezeXml);
      TrackerState trackerState = Req("BasicRequest.xml", squeezeXml);

      Assert.Null(trackerState.Error);
      Assert.Equal(2, trackerState.Position.FullTrack.Length);

      Assert.Equal("OK", trackerState.Position.CurrPoint.LocationType);
      Assert.Equal(1, trackerState.Position.CurrPoint.Latitude);
      Assert.Equal(2, trackerState.Position.CurrPoint.Longitude);

      Assert.Equal("TRACK", trackerState.Position.PreviousPoint.LocationType);
      Assert.Equal(3, trackerState.Position.PreviousPoint.Latitude);
      Assert.Equal(4, trackerState.Position.PreviousPoint.Longitude);

      Assert.True(ReferenceEquals(trackerState.Position.CurrPoint, trackerState.Position.FullTrack[0]));
      Assert.True(ReferenceEquals(trackerState.Position.PreviousPoint, trackerState.Position.FullTrack[1]));

      Assert.True(trackerState.Position.CurrPoint.ForeignTime > trackerState.Position.PreviousPoint.ForeignTime);
    }

    [Theory]
    [InlineData(true)]
    [InlineData(false)]
    public void CombinationsTest(bool squeezeXml)
    {
      _output.WriteLine("squeezeXml: " + squeezeXml);

      const string resourceName = "Combinations.xml";
      string xml = GetResourceAsString(resourceName);
      XDocument doc = XDocument.Load(new StringReader(xml));
      IEnumerable<XElement> messageElements = doc.XPathSelectElements("/response/feedMessageResponse/messages/message");
      int messagesCount = messageElements.Count();

      TrackerState trackerState = Req(resourceName, squeezeXml);

      Assert.Null(trackerState.Error);

      // Some of the elements are intentionally not valid in the test XML:
      Assert.Equal(messagesCount - 4, trackerState.Position.FullTrack.Length);

      DateTime? time = null;
      for (var iMessage = 0; iMessage < trackerState.Position.FullTrack.Length; iMessage++)
      {
        TrackPointData pointData = trackerState.Position.FullTrack[iMessage];
        try
        {
          if (time == null)
          {
            time = pointData.ForeignTime;
          }

          double latitude = pointData.Latitude;
          Assert.True((int)latitude == 1 || (int)latitude == 2 || (int)latitude == 11 || (int)latitude == 12);

          double longitude = pointData.Longitude;
          Assert.True((int)longitude == 20 || (int)longitude == 21);

          Assert.Equal(DateTimeKind.Utc, pointData.ForeignTime.Kind);
          Assert.Equal(time, pointData.ForeignTime);

          bool shouldHaveMessage = (int)latitude == 1 || (int)latitude == 11;
          bool shouldHaveAltitude = (int)latitude == 11 || (int)latitude == 12;
          bool isOk = (int)longitude == 20;
          bool isTrack = (int)longitude == 21;

          time = time.Value.AddMinutes(-10);

          if (shouldHaveAltitude)
            Assert.Equal(123, pointData.Altitude);
          else
            Assert.Null(pointData.Altitude);

          if (isTrack)
            Assert.Equal("TRACK", pointData.LocationType);

          if (isOk)
            Assert.Equal("OK", pointData.LocationType);

          if (shouldHaveMessage)
            Assert.Equal("Need beer and retrieve", pointData.UserMessage);
          else
            Assert.Null(pointData.UserMessage);
        }
        catch
        {
          _output.WriteLine($"Problem with message #{iMessage}");
          throw;
        }
      }
    }

    private static TrackerState Req(string resourceName, bool squeezeXml)
    {
      string xml = ProcessTestXml(resourceName, squeezeXml);
      var request = new SpotFeedRequest("test", xml, 1);

      TrackerState result = null;

      request.BeginRequest(asyncResult =>
      {
        result = request.EndRequest(asyncResult);
      }, null);

      Assert.NotNull(result);

      return result;
    }

    private static string GetResourceAsString(string resourceName)
    {
      Assembly assembly = Assembly.GetExecutingAssembly();

      using (Stream stream = assembly.GetManifestResourceStream("LocationLib.Test." + resourceName))
      {
        if (stream == null)
          throw new FileNotFoundException($"Cannot find resource '{resourceName}'");

        using (StreamReader reader = new StreamReader(stream))
        {
          return reader.ReadToEnd();
        }
      }
    }

    [Fact(
      Skip = "Utility feature, don't need it for normal unit tests check"
      )]
    public void ReplaceTestXml()
    {
      _output.WriteLine(ProcessTestXml("Combinations.xml", false));
    }


    // Utility method to make date-time in test XML going backwards properly with each message
    private static string ProcessTestXml(string resourceName, bool squeezeXml)
    {
{'fraction_non_alphanumeric': 0.10575208782959557, 'fraction_numerical': 0.006756122736229708, 'mean_word_length': 2.963555224990703, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 14}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6526900', 'n_tokens_mistral': 3059, 'n_tokens_neox': 2883, 'n_words': 604}