defmodule Bolt.Sips.Internals.PackStream.EncoderV2Test do
  use ExUnit.Case, async: true

  alias Bolt.Sips.Internals.PackStream.EncoderV2
  alias Bolt.Sips.Types.{TimeWithTZOffset, DateTimeWithTZOffset, Duration, Point}
  alias Bolt.Sips.TypesHelper

  doctest Bolt.Sips.Internals.PackStream.EncoderV2

  describe "Encode temporal types:" do
    test "time without timezone" do
      assert <<0xB1, 0x74, 0xCB, 0x0, 0x0, 0x39, 0x8E, 0xD6, 0xF1, 0xF7, 0x68>> ==
               :erlang.iolist_to_binary(EncoderV2.encode_local_time(~T[17:34:45.654321], 2))
    end

    test "time with timezone" do
      ttz = TimeWithTZOffset.create(~T[12:45:30.250000], 3600)

      assert <<0xB2, 0x54, 0xCB, 0x0, 0x0, 0x29, 0xC5, 0xF8, 0x3C, 0x56, 0x80, 0xC9, 0xE, 0x10>> ==
               :erlang.iolist_to_binary(EncoderV2.encode_time_with_tz(ttz, 2))
    end

    test "date post 1970-01-01" do
      assert <<0xB1, 0x44, 0xC9, 0x45, 0x4D>> ==
               :erlang.iolist_to_binary(EncoderV2.encode_date(~D[2018-07-29], 2))
    end

    test "date pre 1970-01-01" do
      assert <<0xB1, 0x44, 0xC9, 0xB6, 0xA0>> ==
               :erlang.iolist_to_binary(EncoderV2.encode_date(~D[1918-07-29], 2))
    end

    test "local datetime" do
      assert <<0xB2, 0x64, 0xCA, 0x5A, 0xC6, 0x17, 0xB8, 0xCA, 0x27, 0x0, 0x25, 0x68>>
      :erlang.iolist_to_binary(EncoderV2.encode_local_datetime(~N[2018-04-05 12:34:00.654321], 2))
    end

    test "datetime with timezone id" do
      dt = TypesHelper.datetime_with_micro(~N[2016-05-24 13:26:08.654321], "Europe/Berlin")

      assert <<0xB3, 0x66, 0xCA, 0x57, 0x44, 0x56, 0x70, 0xCA, 0x27, 0x0, 0x25, 0x68, 0x8D, 0x45,
               0x75, 0x72, 0x6F, 0x70, 0x65, 0x2F, 0x42, 0x65, 0x72, 0x6C, 0x69,
               0x6E>> ==
               :erlang.iolist_to_binary(EncoderV2.encode_datetime_with_tz_id(dt, 2))
    end

    test "datetime with timezone offset" do
      dt = DateTimeWithTZOffset.create(~N[2016-05-24 13:26:08.654321], 7200)

      assert <<0xB3, 0x46, 0xCA, 0x57, 0x44, 0x56, 0x70, 0xCA, 0x27, 0x0, 0x25, 0x68, 0xC9, 0x1C,
               0x20>> == :erlang.iolist_to_binary(EncoderV2.encode_datetime_with_tz_offset(dt, 2))
    end

    test "duration with all values" do
      duration = %Duration{
        years: 1,
        months: 3,
        weeks: 2,
        days: 20,
        hours: 2,
        minutes: 32,
        seconds: 54,
        nanoseconds: 5550
      }

      assert <<0xB4, 0x45, 0xF, 0x22, 0xC9, 0x23, 0xD6, 0xC9, 0x15, 0xAE>> ==
               :erlang.iolist_to_binary(EncoderV2.encode_duration(duration, 2))
    end
  end

  describe "Encode spatial types:" do
    test "cartesian point 2D" do
      assert <<0xB3, 0x58, 0xC9, 0x1C, 0x23, 0xC1, 0x40, 0x44, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC1,
               0x40, 0x46, 0x80, 0x0, 0x0, 0x0, 0x0,
               0x0>> =
               :erlang.iolist_to_binary(
                 EncoderV2.encode_point(Point.create(:cartesian, 40, 45), 2)
               )
    end

    test "geographic point 2D" do
      assert <<0xB3, 0x58, 0xC9, 0x10, 0xE6, 0xC1, 0x40, 0x44, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC1,
               0x40, 0x46, 0x80, 0x0, 0x0, 0x0, 0x0,
               0x0>> =
               :erlang.iolist_to_binary(EncoderV2.encode_point(Point.create(:wgs_84, 40, 45), 2))
    end

    test "cartesian point 3D" do
      assert <<0xB4, 0x59, 0xC9, 0x23, 0xC5, 0xC1, 0x40, 0x44, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC1,
               0x40, 0x46, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC1, 0x40, 0x62, 0xC0, 0x0, 0x0, 0x0,
               0x0,
               0x0>> =
               :erlang.iolist_to_binary(
                 EncoderV2.encode_point(Point.create(:cartesian, 40, 45, 150), 2)
               )
    end

    test "geographic point 3D" do
      assert <<0xB4, 0x59, 0xC9, 0x13, 0x73, 0xC1, 0x40, 0x44, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC1,
               0x40, 0x46, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC1, 0x40, 0x62, 0xC0, 0x0, 0x0, 0x0,
               0x0,
               0x0>> =
               :erlang.iolist_to_binary(
                 EncoderV2.encode_point(Point.create(:wgs_84, 40, 45, 150), 2)
               )
    end
  end
end
