from ichnaea.api.locate.constants import DataAccuracy, DataSource
from ichnaea.api.locate.query import Query
from ichnaea.api.locate.result import (
    Position,
    PositionResultList,
    Region,
    RegionResultList,
    Result,
    ResultList,
)
from ichnaea.models import encode_mac
from ichnaea.tests.factories import WifiShardFactory


class TestResult(object):
    def test_repr(self):
        result = Result(region_code="DE", lat=1.0)
        rep = repr(result)
        assert rep.startswith("Result")
        assert "DE" not in rep
        assert "1.0" not in rep

    def test_data_accuracy(self):
        assert Result().data_accuracy is DataAccuracy.none

    def test_used_networks(self):
        wifi = WifiShardFactory.build()
        network = ("wifi", encode_mac(wifi.mac), True)
        assert Result().used_networks == []
        assert Result(used_networks=[network]).used_networks == [network]


class TestPosition(object):
    def test_repr(self):
        position = Position(lat=1.0, lon=-1.1, accuracy=100.0, score=2.0)
        rep = repr(position)
        assert rep.startswith("Position")
        assert "1.0" in rep
        assert "-1.1" in rep
        assert "100.0" in rep
        assert position.score == 2.0

    def test_json(self):
        assert Position().json() == {"position": {"source": "query"}}
        assert Position(lat=1.0, lon=1.0, accuracy=2.0).json() == {
            "position": {
                "latitude": 1.0,
                "longitude": 1.0,
                "accuracy": 2.0,
                "source": "query",
            }
        }

    def test_data_accuracy(self):
        def check(accuracy, expected):
            pos = Position(lat=1.0, lon=1.0, accuracy=accuracy)
            assert pos.data_accuracy is expected

        check(None, DataAccuracy.none)
        check(0.0, DataAccuracy.high)
        check(100, DataAccuracy.high)
        check(20000.0, DataAccuracy.medium)
        check(10**6, DataAccuracy.low)


class TestRegion(object):
    def test_repr(self):
        region = Region(
            region_code="DE", region_name="Germany", accuracy=100.0, score=2.0
        )
        rep = repr(region)
        assert rep.startswith("Region")
        assert "DE" in rep
        assert "Germany" in rep
        assert region.score == 2.0

    def test_data_accuracy(self):
        assert Region().data_accuracy is DataAccuracy.none
        region = Region(region_code="DE", region_name="Germany", accuracy=100000.0)
        assert region.data_accuracy is DataAccuracy.low
        region = Region(region_code="VA", region_name="Holy See", accuracy=1000.0)
        assert region.data_accuracy is DataAccuracy.medium


class TestResultList(object):
    def _make_result(self):
        return Position(
            lat=1.0, lon=1.0, accuracy=10.0, score=0.5, source=DataSource.internal
        )

    def test_init(self):
        results = ResultList(self._make_result())
        assert len(results) == 1

    def test_repr(self):
        results = ResultList([self._make_result(), self._make_result()])
        rep = repr(results)
        assert rep.startswith("ResultList:")
        assert "Position<" in rep
        assert "lat:1.0" in rep
        assert "lon:1.0" in rep
        assert "accuracy:10.0" in rep
        assert "score:0.5" in rep

    def test_add(self):
        results = ResultList()
        results.add(self._make_result())
        assert len(results) == 1

    def test_add_many(self):
        results = ResultList(self._make_result())
        results.add((self._make_result(), self._make_result()))
        assert len(results) == 3

    def test_len(self):
        results = ResultList()
        results.add(self._make_result())
        results.add(self._make_result())
        assert len(results) == 2

    def test_getitem(self):
        result = self._make_result()
        results = ResultList()
        results.add(result)
        assert results[0] == result

    def test_iterable(self):
        result = self._make_result()
        results = ResultList()
        results.add(result)
        results.add(result)
        for res in results:
            assert res == result


class TestPositionResultList(object):
    def test_repr(self):