# -*- coding: utf-8 -*

# Licensed under a 3-clause BSD style license - see LICENSE.rst
import pytest
import os
import requests

from astropy import coordinates
from astropy.table import Table

from ..core import MOCServer
from astroquery.utils.mocks import MockResponse


pytest.importorskip("mocpy")
pytest.importorskip("regions")

from regions import CircleSkyRegion, PolygonSkyRegion  # noqa: E402


DATA_FILES = {
    "PROPERTIES_SEARCH": "properties.json",
    "HIPS_FROM_SAADA_AND_ALASKY": "hips_from_saada_alasky.json",
}


@pytest.fixture
def patch_get(request):
    mp = request.getfixturevalue("monkeypatch")

    mp.setattr(requests.Session, "request", get_mockreturn)
    return mp


def get_mockreturn(
    self,
    method,
    url,
    data=None,
    timeout=10,
    files=None,
    params=None,
    headers=None,
    **kwargs
):
    filename = data_path(DATA_FILES[data])
    with open(filename, "rb") as infile:
        content = infile.read()
    return MockResponse(content)


def data_path(filename):
    data_dir = os.path.join(os.path.dirname(__file__), "data")
    return os.path.join(data_dir, filename)


"""List of all the constrain we want to test"""


# SPATIAL CONSTRAINTS DEFINITIONS
polygon1 = coordinates.SkyCoord(
    [57.376, 56.391, 56.025, 56.616],
    [24.053, 24.622, 24.049, 24.291],
    frame="icrs",
    unit="deg",
)
polygon2 = coordinates.SkyCoord(
    [58.376, 53.391, 56.025, 54.616],
    [24.053, 25.622, 22.049, 27.291],
    frame="icrs",
    unit="deg",
)

# PROPERTY CONSTRAINTS DEFINITIONS
meta_data_ex = "ID = *SDSS* && moc_sky_fraction<=0.01"
meta_data_hips_from_saada_alasky = (
    "(hips_service_url*=http://saada*) && (hips_service_url*=http://alasky.*)"
)
"""
Combination of one spatial with a property constrain

Each tuple(spatial, property) characterizes a specific query and is tested
with regards to the true results stored in a file located in the data directory

"""


@pytest.mark.parametrize(
    "datafile", ["PROPERTIES_SEARCH", "HIPS_FROM_SAADA_AND_ALASKY"]
)
def test_request_results(patch_get, datafile):
    """
    Compare the request result obtained with the astroquery.Mocserver API

    with the one obtained on the http://alasky.unistra.fr/MocServer/query
    """
    results = MOCServer.query_region(
        get_query_payload=False, verbose=True, data=datafile
    )
    assert isinstance(results, Table)


"""
Spatial Constrains requests

We test a polygon/cone/moc search and ensure the
request param 'intersect' is correct

"""


@pytest.mark.parametrize(
    "RA, DEC, RADIUS", [(10.8, 6.5, 0.5), (25.6, -23.2, 1.1), (150.6, 45.1, 1.5)]
)
def test_cone_search_spatial_request(RA, DEC, RADIUS):
    center = coordinates.SkyCoord(ra=RA, dec=DEC, unit="deg")
    radius = coordinates.Angle(RADIUS, unit="deg")
    cone_region = CircleSkyRegion(center=center, radius=radius)

    request_payload = MOCServer.query_region(
        region=cone_region, get_query_payload=True, intersect="overlaps"
    )

    assert (
        (request_payload["DEC"] == str(DEC))
        and (request_payload["RA"] == str(RA))
        and (request_payload["SR"] == str(RADIUS))
    )


@pytest.mark.parametrize(
    "poly, poly_payload",
    [
        (polygon1, "Polygon 57.376 24.053 56.391 24.622 56.025 24.049 56.616 24.291"),
        (polygon2, "Polygon 58.376 24.053 53.391 25.622 56.025 22.049 54.616 27.291"),
    ],
)
def test_polygon_spatial_request(poly, poly_payload):
    polygon_region = PolygonSkyRegion(vertices=poly)

    request_payload = MOCServer.query_region(
        region=polygon_region, intersect="overlaps", get_query_payload=True
    )

    assert request_payload["stc"] == poly_payload


@pytest.mark.parametrize("intersect", ["encloses", "overlaps", "covers"])
def test_intersect_param(intersect):
    center = coordinates.SkyCoord(ra=10.8, dec=32.2, unit="deg")
    radius = coordinates.Angle(1.5, unit="deg")

    cone_region = CircleSkyRegion(center, radius)
    request_payload = MOCServer.query_region(
        region=cone_region, intersect=intersect, get_query_payload=True
    )
    if intersect == "encloses":
        assert request_payload["intersect"] == "enclosed"
    else:
        assert request_payload["intersect"] == intersect
