"""Strategic conflict detection Subscription query tests:

  - add a few Subscriptions spaced in time and footprints
  - query with various combinations of arguments
"""

import datetime

from monitoring.monitorlib.infrastructure import default_scope
from monitoring.monitorlib import scd
from monitoring.monitorlib.scd import SCOPE_SC

SUB1_ID = '00000088-b268-481c-a32d-6be442000000'
SUB2_ID = '00000017-a3fe-42d6-9f3b-83dec2000000'
SUB3_ID = '0000001b-9c8a-475e-a82d-d81922000000'


LAT0 = 23
LNG0 = 56

# This value should be large enough to ensure areas separated by this distance
# will lie in separate grid cells.
FOOTPRINT_SPACING_M = 10000


def _make_sub1_req():
  time_start = datetime.datetime.utcnow()
  time_end = time_start + datetime.timedelta(minutes=60)
  lat = LAT0 - scd.latitude_degrees(FOOTPRINT_SPACING_M)
  return {
    "extents": scd.make_vol4(None, time_end, 0, 300, scd.make_circle(lat, LNG0, 100)),
    "old_version": 0,
    "uss_base_url": "https://example.com/foo",
    "notify_for_operations": True,
    "notify_for_constraints": False
  }


def _make_sub2_req():
  time_start = datetime.datetime.utcnow() + datetime.timedelta(hours=2)
  time_end = time_start + datetime.timedelta(minutes=60)
  return {
    "extents": scd.make_vol4(time_start, time_end, 350, 650, scd.make_circle(LAT0, LNG0, 100)),
    "old_version": 0,
    "uss_base_url": "https://example.com/foo",
    "notify_for_operations": True,
    "notify_for_constraints": False
  }


def _make_sub3_req():
  time_start = datetime.datetime.utcnow() + datetime.timedelta(hours=4)
  time_end = time_start + datetime.timedelta(minutes=60)
  lat = LAT0 + scd.latitude_degrees(FOOTPRINT_SPACING_M)
  return {
    "extents": scd.make_vol4(time_start, time_end, 700, 1000, scd.make_circle(lat, LNG0, 100)),
    "old_version": 0,
    "uss_base_url": "https://example.com/foo",
    "notify_for_operations": True,
    "notify_for_constraints": False
  }


def test_ensure_clean_workspace(scd_session):
  for sub_id in (SUB1_ID, SUB2_ID, SUB3_ID):
    resp = scd_session.get('/subscriptions/{}'.format(sub_id), scope=SCOPE_SC)
    if resp.status_code == 200:
      resp = scd_session.delete('/subscriptions/{}'.format(sub_id), scope=SCOPE_SC)
      assert resp.status_code == 200, resp.content
    elif resp.status_code == 404:
      # As expected.
      pass
    else:
      assert False, resp.content


# Preconditions: No named Subscriptions exist
# Mutations: None
@default_scope(SCOPE_SC)
def test_subs_do_not_exist_get(scd_session):
  for sub_id in (SUB1_ID, SUB2_ID, SUB3_ID):
    resp = scd_session.get('/subscriptions/{}'.format(sub_id))
    assert resp.status_code == 404, resp.content


# Preconditions: No named Subscriptions exist
# Mutations: None
@default_scope(SCOPE_SC)
def test_subs_do_not_exist_query(scd_session):
  resp = scd_session.post('/subscriptions/query', json={
    'area_of_interest': scd.make_vol4(None, None, 0, 5000, scd.make_circle(LAT0, LNG0, FOOTPRINT_SPACING_M))
  })
  assert resp.status_code == 200, resp.content
  result_ids = [x['id'] for x in resp.json()['subscriptions']]
  for sub_id in (SUB1_ID, SUB2_ID, SUB3_ID):
    assert sub_id not in result_ids


# Preconditions: No named Subscriptions exist
# Mutations: Subscriptions 1, 2, and 3 created
@default_scope(SCOPE_SC)
def test_create_subs(scd_session):
  resp = scd_session.put('/subscriptions/{}'.format(SUB1_ID), json=_make_sub1_req())
  assert resp.status_code == 200, resp.content

  resp = scd_session.put('/subscriptions/{}'.format(SUB2_ID), json=_make_sub2_req())
  assert resp.status_code == 200, resp.content

  resp = scd_session.put('/subscriptions/{}'.format(SUB3_ID), json=_make_sub3_req())
  assert resp.status_code == 200, resp.content


# Preconditions: Subscriptions 1, 2, and 3 created
# Mutations: None
@default_scope(SCOPE_SC)
def test_search_find_all_subs(scd_session):
  resp = scd_session.post(
      '/subscriptions/query',
      json={
        "area_of_interest": scd.make_vol4(None, None, 0, 3000,
                                          scd.make_circle(LAT0, LNG0, FOOTPRINT_SPACING_M))
      })
  assert resp.status_code == 200, resp.content
  result_ids = [x['id'] for x in resp.json()['subscriptions']]
  for sub_id in (SUB1_ID, SUB2_ID, SUB3_ID):
    assert sub_id in result_ids


# Preconditions: Subscriptions 1, 2, and 3 created
# Mutations: None
@default_scope(SCOPE_SC)
def test_search_footprint(scd_session):
  lat = LAT0 - scd.latitude_degrees(FOOTPRINT_SPACING_M)
  print(lat)
  resp = scd_session.post(
    '/subscriptions/query',
    json={
      "area_of_interest": scd.make_vol4(None, None, 0, 3000,
                                        scd.make_circle(lat, LNG0, 50))
    })
  assert resp.status_code == 200, resp.content
  result_ids = [x['id'] for x in resp.json()['subscriptions']]
  assert SUB1_ID in result_ids
  assert SUB2_ID not in result_ids
  assert SUB3_ID not in result_ids

  resp = scd_session.post(
    '/subscriptions/query',
    json={
      "area_of_interest": scd.make_vol4(None, None, 0, 3000,
                                        scd.make_circle(LAT0, LNG0, 50))
    })
  assert resp.status_code == 200, resp.content
  result_ids = [x['id'] for x in resp.json()['subscriptions']]
  assert SUB1_ID not in result_ids
  assert SUB2_ID in result_ids
  assert SUB3_ID not in result_ids


# Preconditions: Subscriptions 1, 2, and 3 created
# Mutations: None
@default_scope(SCOPE_SC)
def test_search_time(scd_session):
  time_start = datetime.datetime.utcnow()
  time_end = time_start + datetime.timedelta(minutes=1)

  resp = scd_session.post(
    '/subscriptions/query',
    json={
      "area_of_interest": scd.make_vol4(time_start, time_end, 0, 3000,
                                        scd.make_circle(LAT0, LNG0, FOOTPRINT_SPACING_M))
    })
  assert resp.status_code == 200, resp.content
  result_ids = [x['id'] for x in resp.json()['subscriptions']]
  assert SUB1_ID in result_ids
  assert SUB2_ID not in result_ids
  assert SUB3_ID not in result_ids

  resp = scd_session.post(
    '/subscriptions/query',
    json={
      "area_of_interest": scd.make_vol4(None, time_end, 0, 3000,
                                        scd.make_circle(LAT0, LNG0, FOOTPRINT_SPACING_M))
    })
  assert resp.status_code == 200, resp.content
  result_ids = [x['id'] for x in resp.json()['subscriptions']]
  assert SUB1_ID in result_ids
  assert SUB2_ID not in result_ids
  assert SUB3_ID not in result_ids

  time_start = datetime.datetime.utcnow() + datetime.timedelta(hours=4)
  time_end = time_start + datetime.timedelta(minutes=1)

  resp = scd_session.post(
    '/subscriptions/query',
    json={
      "area_of_interest": scd.make_vol4(time_start, time_end, 0, 3000,
                                        scd.make_circle(LAT0, LNG0, FOOTPRINT_SPACING_M))
    })
  assert resp.status_code == 200, resp.content
  result_ids = [x['id'] for x in resp.json()['subscriptions']]
  assert SUB1_ID not in result_ids
  assert SUB2_ID not in result_ids
  assert SUB3_ID in result_ids

  resp = scd_session.post(
    '/subscriptions/query',
    json={
      "area_of_interest": scd.make_vol4(time_start, None, 0, 3000,
                                        scd.make_circle(LAT0, LNG0, FOOTPRINT_SPACING_M))
    })
  assert resp.status_code == 200, resp.content
  result_ids = [x['id'] for x in resp.json()['subscriptions']]
  assert SUB1_ID not in result_ids
  assert SUB2_ID not in result_ids
  assert SUB3_ID in result_ids


# Preconditions: Subscriptions 1, 2, and 3 created
# Mutations: None
@default_scope(SCOPE_SC)
def test_search_time_footprint(scd_session):
  time_start = datetime.datetime.utcnow()
  time_end = time_start + datetime.timedelta(hours=2.5)
  lat = LAT0 + scd.latitude_degrees(FOOTPRINT_SPACING_M)
  resp = scd_session.post(
    '/subscriptions/query',
    json={
      "area_of_interest": scd.make_vol4(time_start, time_end, 0, 3000,
                                        scd.make_circle(lat, LNG0, FOOTPRINT_SPACING_M))
    })
  assert resp.status_code == 200, resp.content
  result_ids = [x['id'] for x in resp.json()['subscriptions']]
  assert SUB1_ID not in result_ids
  assert SUB2_ID in result_ids
  assert SUB3_ID not in result_ids



# Preconditions: Subscriptions 1, 2, and 3 created
# Mutations: Subscriptions 1, 2, and 3 deleted
@default_scope(SCOPE_SC)
def test_delete_subs(scd_session):
  for sub_id in (SUB1_ID, SUB2_ID, SUB3_ID):
    resp = scd_session.delete('/subscriptions/{}'.format(sub_id))
    assert resp.status_code == 200, resp.content

"""Strategic conflict detection Subscription query tests:

  - add a few Subscriptions spaced in time and footprints
  - query with various combinations of arguments
"""

import datetime

from monitoring.monitorlib.infrastructure import default_scope
from monitoring.monitorlib import scd
from monitoring.monitorlib.scd import SCOPE_SC

SUB1_ID = '00000088-b268-481c-a32d-6be442000000'
SUB2_ID = '00000017-a3fe-42d6-9f3b-83dec2000000'
SUB3_ID = '0000001b-9c8a-475e-a82d-d81922000000'


LAT0 = 23
LNG0 = 56

# This value should be large enough to ensure areas separated by this distance
# will lie in separate grid cells.
FOOTPRINT_SPACING_M = 10000


def _make_sub1_req():
  time_start = datetime.datetime.utcnow()
  time_end = time_start + datetime.timedelta(minutes=60)
  lat = LAT0 - scd.latitude_degrees(FOOTPRINT_SPACING_M)
  return {
    "extents": scd.make_vol4(None, time_end, 0, 300, scd.make_circle(lat, LNG0, 100)),
    "old_version": 0,
    "uss_base_url": "https://example.com/foo",
    "notify_for_operations": True,
    "notify_for_constraints": False
  }


def _make_sub2_req():
  time_start = datetime.datetime.utcnow() + datetime.timedelta(hours=2)
  time_end = time_start + datetime.timedelta(minutes=60)
  return {
    "extents": scd.make_vol4(time_start, time_end, 350, 650, scd.make_circle(LAT0, LNG0, 100)),
    "old_version": 0,
    "uss_base_url": "https://example.com/foo",
    "notify_for_operations": True,
    "notify_for_constraints": False
  }


def _make_sub3_req():
  time_start = datetime.datetime.utcnow() + datetime.timedelta(hours=4)
  time_end = time_start + datetime.timedelta(minutes=60)
  lat = LAT0 + scd.latitude_degrees(FOOTPRINT_SPACING_M)
  return {
    "extents": scd.make_vol4(time_start, time_end, 700, 1000, scd.make_circle(lat, LNG0, 100)),
    "old_version": 0,
    "uss_base_url": "https://example.com/foo",
    "notify_for_operations": True,
    "notify_for_constraints": False
  }


def test_ensure_clean_workspace(scd_session):
  for sub_id in (SUB1_ID, SUB2_ID, SUB3_ID):
    resp = scd_session.get('/subscriptions/{}'.format(sub_id), scope=SCOPE_SC)
    if resp.status_code == 200:
      resp = scd_session.delete('/subscriptions/{}'.format(sub_id), scope=SCOPE_SC)
      assert resp.status_code == 200, resp.content
    elif resp.status_code == 404:
      # As expected.
      pass
    else:
      assert False, resp.content


# Preconditions: No named Subscriptions exist
# Mutations: None
@default_scope(SCOPE_SC)
def test_subs_do_not_exist_get(scd_session):
  for sub_id in (SUB1_ID, SUB2_ID, SUB3_ID):
    resp = scd_session.get('/subscriptions/{}'.format(sub_id))
    assert resp.status_code == 404, resp.content


# Preconditions: No named Subscriptions exist
# Mutations: None
@default_scope(SCOPE_SC)
def test_subs_do_not_exist_query(scd_session):
  resp = scd_session.post('/subscriptions/query', json={
    'area_of_interest': scd.make_vol4(None, None, 0, 5000, scd.make_circle(LAT0, LNG0, FOOTPRINT_SPACING_M))
  })
  assert resp.status_code == 200, resp.content
  result_ids = [x['id'] for x in resp.json()['subscriptions']]
  for sub_id in (SUB1_ID, SUB2_ID, SUB3_ID):
    assert sub_id not in result_ids


# Preconditions: No named Subscriptions exist
# Mutations: Subscriptions 1, 2, and 3 created
@default_scope(SCOPE_SC)
def test_create_subs(scd_session):
  resp = scd_session.put('/subscriptions/{}'.format(SUB1_ID), json=_make_sub1_req())
  assert resp.status_code == 200, resp.content

  resp = scd_session.put('/subscriptions/{}'.format(SUB2_ID), json=_make_sub2_req())
  assert resp.status_code == 200, resp.content

  resp = scd_session.put('/subscriptions/{}'.format(SUB3_ID), json=_make_sub3_req())
  assert resp.status_code == 200, resp.content


# Preconditions: Subscriptions 1, 2, and 3 created
# Mutations: None
@default_scope(SCOPE_SC)
def test_search_find_all_subs(scd_session):
  resp = scd_session.post(
      '/subscriptions/query',
      json={
        "area_of_interest": scd.make_vol4(None, None, 0, 3000,
                                          scd.make_circle(LAT0, LNG0, FOOTPRINT_SPACING_M))
      })
  assert resp.status_code == 200, resp.content
  result_ids = [x['id'] for x in resp.json()['subscriptions']]
  for sub_id in (SUB1_ID, SUB2_ID, SUB3_ID):
    assert sub_id in result_ids


# Preconditions: Subscriptions 1, 2, and 3 created
# Mutations: None
@default_scope(SCOPE_SC)
def test_search_footprint(scd_session):
  lat = LAT0 - scd.latitude_degrees(FOOTPRINT_SPACING_M)
  print(lat)
  resp = scd_session.post(
    '/subscriptions/query',
    json={
      "area_of_interest": scd.make_vol4(None, None, 0, 3000,
                                        scd.make_circle(lat, LNG0, 50))
    })
  assert resp.status_code == 200, resp.content
  result_ids = [x['id'] for x in resp.json()['subscriptions']]
  assert SUB1_ID in result_ids
  assert SUB2_ID not in result_ids
  assert SUB3_ID not in result_ids

  resp = scd_session.post(
    '/subscriptions/query',
    json={
      "area_of_interest": scd.make_vol4(None, None, 0, 3000,
                                        scd.make_circle(LAT0, LNG0, 50))
    })
  assert resp.status_code == 200, resp.content
  result_ids = [x['id'] for x in resp.json()['subscriptions']]
  assert SUB1_ID not in result_ids
  assert SUB2_ID in result_ids
  assert SUB3_ID not in result_ids


# Preconditions: Subscriptions 1, 2, and 3 created
# Mutations: None
@default_scope(SCOPE_SC)
def test_search_time(scd_session):
  time_start = datetime.datetime.utcnow()
  time_end = time_start + datetime.timedelta(minutes=1)

  resp = scd_session.post(
    '/subscriptions/query',
    json={
      "area_of_interest": scd.make_vol4(time_start, time_end, 0, 3000,
                                        scd.make_circle(LAT0, LNG0, FOOTPRINT_SPACING_M))
    })
  assert resp.status_code == 200, resp.content
  result_ids = [x['id'] for x in resp.json()['subscriptions']]
  assert SUB1_ID in result_ids
  assert SUB2_ID not in result_ids
  assert SUB3_ID not in result_ids

  resp = scd_session.post(
    '/subscriptions/query',
    json={
      "area_of_interest": scd.make_vol4(None, time_end, 0, 3000,
                                        scd.make_circle(LAT0, LNG0, FOOTPRINT_SPACING_M))
    })
  assert resp.status_code == 200, resp.content
  result_ids = [x['id'] for x in resp.json()['subscriptions']]
  assert SUB1_ID in result_ids
  assert SUB2_ID not in result_ids
  assert SUB3_ID not in result_ids

  time_start = datetime.datetime.utcnow() + datetime.timedelta(hours=4)
  time_end = time_start + datetime.timedelta(minutes=1)

  resp = scd_session.post(
    '/subscriptions/query',
    json={
      "area_of_interest": scd.make_vol4(time_start, time_end, 0, 3000,
                                        scd.make_circle(LAT0, LNG0, FOOTPRINT_SPACING_M))
    })
  assert resp.status_code == 200, resp.content
  result_ids = [x['id'] for x in resp.json()['subscriptions']]
  assert SUB1_ID not in result_ids
  assert SUB2_ID not in result_ids
  assert SUB3_ID in result_ids

  resp = scd_session.post(
    '/subscriptions/query',
    json={
      "area_of_interest": scd.make_vol4(time_start, None, 0, 3000,
                                        scd.make_circle(LAT0, LNG0, FOOTPRINT_SPACING_M))
    })
  assert resp.status_code == 200, resp.content
  result_ids = [x['id'] for x in resp.json()['subscriptions']]
  assert SUB1_ID not in result_ids
  assert SUB2_ID not in result_ids
  assert SUB3_ID in result_ids


# Preconditions: Subscriptions 1, 2, and 3 created
# Mutations: None
@default_scope(SCOPE_SC)
def test_search_time_footprint(scd_session):
  time_start = datetime.datetime.utcnow()
  time_end = time_start + datetime.timedelta(hours=2.5)
  lat = LAT0 + scd.latitude_degrees(FOOTPRINT_SPACING_M)
  resp = scd_session.post(
    '/subscriptions/query',
    json={
      "area_of_interest": scd.make_vol4(time_start, time_end, 0, 3000,
                                        scd.make_circle(lat, LNG0, FOOTPRINT_SPACING_M))
    })
  assert resp.status_code == 200, resp.content
  result_ids = [x['id'] for x in resp.json()['subscriptions']]
  assert SUB1_ID not in result_ids
  assert SUB2_ID in result_ids
  assert SUB3_ID not in result_ids



# Preconditions: Subscriptions 1, 2, and 3 created
# Mutations: Subscriptions 1, 2, and 3 deleted
@default_scope(SCOPE_SC)
def test_delete_subs(scd_session):
  for sub_id in (SUB1_ID, SUB2_ID, SUB3_ID):
    resp = scd_session.delete('/subscriptions/{}'.format(sub_id))
    assert resp.status_code == 200, resp.content

Strategic conflict detection Subscription query tests:    - add a few Subscriptions spaced in time and footprints   - query with various combinations of arguments # This value should be large enough to ensure areas separated by this distance # will lie in separate grid cells. # As expected. # Preconditions: No named Subscriptions exist # Mutations: None # Preconditions: No named Subscriptions exist # Mutations: None # Preconditions: No named Subscriptions exist # Mutations: Subscriptions 1, 2, and 3 created # Preconditions: Subscriptions 1, 2, and 3 created # Mutations: None # Preconditions: Subscriptions 1, 2, and 3 created # Mutations: None # Preconditions: Subscriptions 1, 2, and 3 created # Mutations: None # Preconditions: Subscriptions 1, 2, and 3 created # Mutations: None # Preconditions: Subscriptions 1, 2, and 3 created # Mutations: Subscriptions 1, 2, and 3 deleted