# Generated by Django 2.2.1 on 2019-09-19 07:44

from django.db import migrations, transaction
from django.db.models import Q
from model_utils import Choices


SCALES = Choices(
    (1, "commune", "Commune"),
    (5, "epci", "EPCI"),
    (8, "basin", "Bassin hydrographique"),
    (10, "department", "Département"),
    (15, "region", "Région"),
    (16, "overseas", "Outre-mer"),
    (17, "mainland", "Métropole"),
    (18, "adhoc", "Ad-hoc"),
    (20, "country", "Pays"),
    (25, "continent", "Continent"),
)


@transaction.atomic
def update_links(apps, schema_editor):
    """Set data for the newly added `contained_in` Perimeter field.

    This method is grossly inefficient, which is not a big deal because
    it will be ran only once.

    """
    Perimeter = apps.get_model("geofr", "Perimeter")
    perimeters = Perimeter.objects.exclude(
        scale__in=(SCALES.country, SCALES.continent)
    ).order_by("scale")

    PerimeterContainedIn = Perimeter.contained_in.through
    containments = []

    try:
        france = Perimeter.objects.get(scale=SCALES.country)
        europe = Perimeter.objects.get(scale=SCALES.continent)
    except:
        # Don't raise exception to not prevent the creation of the
        # test database
        return

    nb_perimeters = perimeters.count()
    counter = 0

    for perimeter in perimeters:
        if counter % 100 == 0:
            pc = counter / nb_perimeters * 100.0
            print("{} / {} ({:.2f}%%)".format(counter, nb_perimeters, pc))

        containing_perimeters = Perimeter.objects.filter(
            (Q(scale=SCALES.epci) & Q(code=perimeter.epci))
            | (Q(scale=SCALES.department) & Q(code__in=perimeter.departments))
            | (Q(scale=SCALES.region) & Q(code__in=perimeter.regions))
            | (Q(scale=SCALES.basin) & Q(code=perimeter.basin))
        )

        for containing in containing_perimeters:
            containments.append(
                PerimeterContainedIn(
                    from_perimeter_id=perimeter.id, to_perimeter_id=containing.id
                )
            )

        containments.append(
            PerimeterContainedIn(
                from_perimeter_id=perimeter.id, to_perimeter_id=france.id
            )
        )
        containments.append(
            PerimeterContainedIn(
                from_perimeter_id=perimeter.id, to_perimeter_id=europe.id
            )
        )

        counter += 1

    containments.append(
        PerimeterContainedIn(from_perimeter_id=france.id, to_perimeter_id=europe.id)
    )

    PerimeterContainedIn.objects.bulk_create(containments)


def remove_links(apps, schema_editor):
    Perimeter = apps.get_model("geofr", "Perimeter")
    PerimeterContainedIn = Perimeter.contained_in.through
    PerimeterContainedIn.objects.all().delete()


class Migration(migrations.Migration):

    dependencies = [
        ("geofr", "0021_perimeter_contained_in"),
    ]

    operations = [
        migrations.RunPython(update_links, remove_links),
    ]
