# Generated by Django 2.2.9 on 2020-04-30 17:16

import os
import uuid
import datetime
from django.db.models import Q
from django.db import migrations, models


def setup(apps):
    nodes = apps.get_model("models", "Node")
    tiles = apps.get_model("models", "Tile")
    relations = apps.get_model("models", "ResourceXResource")
    resource = apps.get_model("models", "Resource")
    resource_instance_nodes = {
        str(node["nodeid"]): node["datatype"]
        for node in nodes.objects.filter(
            Q(datatype="resource-instance") | Q(datatype="resource-instance-list")
        ).values("nodeid", "datatype")
    }
    resource_instance_tiles = (
        tiles.objects.filter(
            Q(nodegroup_id__node__datatype="resource-instance")
            | Q(nodegroup_id__node__datatype="resource-instance-list")
        )
        .distinct()
        .iterator(chunk_size=1000)
    )
    root_ontology_classes = {
        str(node["graph_id"]): node["ontologyclass"]
        for node in nodes.objects.filter(istopnode=True).values(
            "graph_id", "ontologyclass"
        )
    }

    return (
        resource,
        relations,
        resource_instance_nodes,
        resource_instance_tiles,
        root_ontology_classes,
    )


def create_relation(
    relations,
    resource,
    resourceinstanceid_from,
    resourceinstanceid_to,
    tileid,
    nodeid,
    root_ontology_classes,
):
    relationid = uuid.uuid4()
    relations.objects.create(
        resourcexid=relationid,
        resourceinstanceidfrom_id=resourceinstanceid_from,
        resourceinstanceidto_id=resourceinstanceid_to,
        tileid_id=tileid,
        nodeid_id=nodeid,
        modified=datetime.datetime.now(),
        created=datetime.datetime.now(),
    )

    ret = {
        "resourceId": resourceinstanceid_to,
        "ontologyProperty": "",
        "inverseOntologyProperty": "",
        "resourceXresourceId": str(relationid),
    }
    return ret


def create_resource_instance_tiledata(relations, tile, nodeid, datatype):
    if tile.data[nodeid] is None:
        return None
    else:
        new_tile_data = []
        for resourceRelationItem in tile.data[nodeid]:
            relation = relations.objects.get(
                resourcexid=resourceRelationItem["resourceXresourceId"]
            )
            relation.delete()
            new_tile_data.append(str(resourceRelationItem["resourceId"]))

        if datatype == "resource-instance-list":
            return new_tile_data
        else:
            return new_tile_data[0]


def forward_migrate(apps, schema_editor, with_create_permissions=True):
    (
        resource,
        relations,
        resource_instance_nodes,
        resource_instance_tiles,
        root_ontology_classes,
    ) = setup(apps)
    # iterate over resource-instance tiles and identify resource-instance nodes
    for tile in resource_instance_tiles:
        for nodeid in tile.data.keys():
            if nodeid in resource_instance_nodes and tile.data[nodeid] is not None:
                # check if data is a list or string then replace resourceinstanceids with relationids
                new_tile_resource_data = []
                if isinstance(tile.data[nodeid], list):
                    for resourceinstanceidto in tile.data[nodeid]:
                        new_tile_resource_data.append(
                            create_relation(
                                relations,
                                resource,
                                tile.resourceinstance_id,
                                resourceinstanceidto,
                                tile.tileid,
                                nodeid,
                                root_ontology_classes,
                            )
                        )
                else:
                    new_tile_resource_data.append(
                        create_relation(
                            relations,
                            resource,
                            tile.resourceinstance_id,
                            tile.data[nodeid],
                            tile.tileid,
                            nodeid,
                            root_ontology_classes,
                        )
                    )

                tile.data[nodeid] = new_tile_resource_data
                tile.save()


def reverse_migrate(apps, schema_editor, with_create_permissions=True):
    (
        resource,
        relations,
        resource_instance_nodes,
        resource_instance_tiles,
        root_ontology_classes,
    ) = setup(apps)
    for tile in resource_instance_tiles:
        for nodeid in tile.data.keys():
            if (
                nodeid in resource_instance_nodes.keys()
                and tile.data[nodeid] is not None
            ):
                tile.data[nodeid] = create_resource_instance_tiledata(
                    relations, tile, nodeid, resource_instance_nodes[nodeid]
                )
                tile.save()


class Migration(migrations.Migration):

    dependencies = [
        ("models", "6019_node_config_for_resource_instance"),
    ]

    operations = [
        migrations.RunPython(forward_migrate, reverse_migrate),
    ]
