from contextlib import contextmanager, closing

import pytest
import sqlalchemy
from sqlalchemy.sql.schema import Table as DbTable

from tests.conftest import area_polyfile_string
from tests.inside_worker_test.conftest import slow
from tests.inside_worker_test.declarative_schema import osm_models


@pytest.fixture
def graveyard_polygon(osm_tags):
    return {osm_models.t_osm_polygon: osm_tags}


@pytest.fixture
def graveyard_point(osm_tags):
    return {osm_models.t_osm_point: osm_tags}


@pytest.fixture(
    params=[
        dict(amenity='grave_yard', religion='any value will do, as long as one is present'),
        dict(amenity='grave_yard'),
        dict(landuse='cemetery', religion='any value will do, as long as one is present'),
        dict(landuse='cemetery'),
    ],
    ids=[
        'amenity=grave_yard with religion=*',
        'amenity=grave_yard without religion',
        'landuse=cemetery with religion=*',
        'landuse=cemetery without religion',
    ]
)
def osm_tags(request):
    return request.param


@slow
def test_osmaxx_data_model_processing_does_not_put_amenity_grave_yard_into_table_pow_a(
        graveyard_polygon, data_import):
    with data_import(graveyard_polygon) as engine:
        t_pow_a = DbTable('pow_a', osm_models.metadata, schema='osmaxx')
        with closing(engine.execute(sqlalchemy.select([t_pow_a]))) as result:
            assert result.rowcount == 0


@slow
def test_osmaxx_data_model_processing_puts_amenity_grave_yard_into_table_poi_a(
        graveyard_polygon, data_import):
    with data_import(graveyard_polygon) as engine:
        t_poi_a = DbTable('poi_a', osm_models.metadata, schema='osmaxx')
        with closing(engine.execute(sqlalchemy.select([t_poi_a]))) as result:
            assert result.rowcount == 1


@slow
def test_osmaxx_data_model_processing_does_not_put_amenity_grave_yard_into_table_landuse_a(
        graveyard_polygon, data_import):
    with data_import(graveyard_polygon) as engine:
        t_landuse_a = DbTable('landuse_a', osm_models.metadata, schema='osmaxx')
        with closing(engine.execute(sqlalchemy.select([t_landuse_a]))) as result:
            assert result.rowcount == 0


@slow
def test_osmaxx_data_model_processing_does_not_put_amenity_grave_yard_into_table_pow_p(
        graveyard_polygon, data_import):
    with data_import(graveyard_polygon) as engine:
        t_pow_p = DbTable('pow_p', osm_models.metadata, schema='osmaxx')
        with closing(engine.execute(sqlalchemy.select([t_pow_p]))) as result:
            assert result.rowcount == 0


@slow
def test_osmaxx_data_model_processing_puts_amenity_grave_yard_into_table_poi_p(
        graveyard_polygon, data_import):
    with data_import(graveyard_polygon) as engine:
        t_poi_p = DbTable('poi_p', osm_models.metadata, schema='osmaxx')
        with closing(engine.execute(sqlalchemy.select([t_poi_p]))) as result:
            assert result.rowcount == 1


@slow
def test_osmaxx_data_model_processing_does_not_put_amenity_grave_yard_point_into_table_pow_p(
        graveyard_point, data_import):
    with data_import(graveyard_point) as engine:
        t_pow_p = DbTable('pow_p', osm_models.metadata, schema='osmaxx')
        with closing(engine.execute(sqlalchemy.select([t_pow_p]))) as result:
            assert result.rowcount == 0


@slow
def test_osmaxx_data_model_processing_puts_amenity_grave_yard_point_into_table_poi_p(
        graveyard_point, data_import):
    with data_import(graveyard_point) as engine:
        t_poi_p = DbTable('poi_p', osm_models.metadata, schema='osmaxx')
        with closing(engine.execute(sqlalchemy.select([t_poi_p]))) as result:
            assert result.rowcount == 1


@pytest.fixture()
def data_import(osmaxx_schemas, clean_osm_tables, monkeypatch):
    from tests.inside_worker_test.conftest import cleanup_osmaxx_schemas
    from osmaxx.conversion.converters.converter_gis.bootstrap.bootstrap import BootStrapper

    assert osmaxx_schemas == clean_osm_tables  # same db-connection
    engine = osmaxx_schemas
    monkeypatch.setattr(
        'osmaxx.conversion.converters.converter_gis.helper.postgres_wrapper.create_engine', lambda *_, **__: engine)

    class _BootStrapperWithoutPbfFile(BootStrapper):
        def __init__(self, data):
            super().__init__(area_polyfile_string=area_polyfile_string())
            self.data = data

        def _reset_database(self):
            pass  # Already taken care of by clean_osm_tables fixture.

        def _import_from_world_db(self, with_boundaries):
            for table, values in self.data.items():
                engine.execute(table.insert().execution_options(autocommit=True), values)

        def _setup_db_functions(self):
            pass  # Already taken care of by osmaxx_functions fixture.

    @contextmanager
    def import_data(data):
        bootstrapper = _BootStrapperWithoutPbfFile(data)
        try:
            bootstrapper.bootstrap()
            yield engine
        finally:
            cleanup_osmaxx_schemas(bootstrapper._postgres._engine)

    return import_data

@@ -1085,33 +1085,28 @@
 not_put_
-amenity_grave_yar
+burial_groun
 d_into_t
@@ -1451,33 +1451,28 @@
 ng_puts_
-amenity_grave_yar
+burial_groun
 d_into_t
@@ -1825,33 +1825,28 @@
 not_put_
-amenity_grave_yar
+burial_groun
 d_into_t
@@ -2215,33 +2215,28 @@
 not_put_
-amenity_grave_yar
+burial_groun
 d_into_t
@@ -2581,33 +2581,28 @@
 ng_puts_
-amenity_grave_yar
+burial_groun
 d_into_t
@@ -2955,33 +2955,28 @@
 not_put_
-amenity_grave_yar
+burial_groun
 d_point_
@@ -3327,25 +3327,20 @@
 uts_
-amenity_grave_yar
+burial_groun
 d_po

rename tests to account for additional fixture parameters #477