"""
Add V2_2 data models for Manifest, ManifestBlob and ManifestLegacyImage.

Revision ID: 9093adccc784
Revises: 6c21e2cfb8b6
Create Date: 2018-08-06 16:07:50.222749
"""

# revision identifiers, used by Alembic.
revision = "9093adccc784"
down_revision = "6c21e2cfb8b6"

import sqlalchemy as sa
from image.docker.schema1 import DOCKER_SCHEMA1_CONTENT_TYPES


def upgrade(op, tables, tester):
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table(
        "manifest",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("repository_id", sa.Integer(), nullable=False),
        sa.Column("digest", sa.String(length=255), nullable=False),
        sa.Column("media_type_id", sa.Integer(), nullable=False),
        sa.Column("manifest_bytes", sa.Text(), nullable=False),
        sa.ForeignKeyConstraint(
            ["media_type_id"], ["mediatype.id"], name=op.f("fk_manifest_media_type_id_mediatype")
        ),
        sa.ForeignKeyConstraint(
            ["repository_id"], ["repository.id"], name=op.f("fk_manifest_repository_id_repository")
        ),
        sa.PrimaryKeyConstraint("id", name=op.f("pk_manifest")),
    )
    op.create_index("manifest_digest", "manifest", ["digest"], unique=False)
    op.create_index("manifest_media_type_id", "manifest", ["media_type_id"], unique=False)
    op.create_index("manifest_repository_id", "manifest", ["repository_id"], unique=False)
    op.create_index(
        "manifest_repository_id_digest", "manifest", ["repository_id", "digest"], unique=True
    )
    op.create_index(
        "manifest_repository_id_media_type_id",
        "manifest",
        ["repository_id", "media_type_id"],
        unique=False,
    )
    op.create_table(
        "manifestblob",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("repository_id", sa.Integer(), nullable=False),
        sa.Column("manifest_id", sa.Integer(), nullable=False),
        sa.Column("blob_id", sa.Integer(), nullable=False),
        sa.Column("blob_index", sa.Integer(), nullable=False),
        sa.ForeignKeyConstraint(
            ["blob_id"], ["imagestorage.id"], name=op.f("fk_manifestblob_blob_id_imagestorage")
        ),
        sa.ForeignKeyConstraint(
            ["manifest_id"], ["manifest.id"], name=op.f("fk_manifestblob_manifest_id_manifest")
        ),
        sa.ForeignKeyConstraint(
            ["repository_id"],
            ["repository.id"],
            name=op.f("fk_manifestblob_repository_id_repository"),
        ),
        sa.PrimaryKeyConstraint("id", name=op.f("pk_manifestblob")),
    )
    op.create_index("manifestblob_blob_id", "manifestblob", ["blob_id"], unique=False)
    op.create_index("manifestblob_manifest_id", "manifestblob", ["manifest_id"], unique=False)
    op.create_index(
        "manifestblob_manifest_id_blob_id", "manifestblob", ["manifest_id", "blob_id"], unique=True
    )
    op.create_index(
        "manifestblob_manifest_id_blob_index",
        "manifestblob",
        ["manifest_id", "blob_index"],
        unique=True,
    )
    op.create_index("manifestblob_repository_id", "manifestblob", ["repository_id"], unique=False)
    op.create_table(
        "manifestlabel",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("repository_id", sa.Integer(), nullable=False),
        sa.Column("manifest_id", sa.Integer(), nullable=False),
        sa.Column("label_id", sa.Integer(), nullable=False),
        sa.ForeignKeyConstraint(
            ["label_id"], ["label.id"], name=op.f("fk_manifestlabel_label_id_label")
        ),
        sa.ForeignKeyConstraint(
            ["manifest_id"], ["manifest.id"], name=op.f("fk_manifestlabel_manifest_id_manifest")
        ),
        sa.ForeignKeyConstraint(
            ["repository_id"],
            ["repository.id"],
            name=op.f("fk_manifestlabel_repository_id_repository"),
        ),
        sa.PrimaryKeyConstraint("id", name=op.f("pk_manifestlabel")),
    )
    op.create_index("manifestlabel_label_id", "manifestlabel", ["label_id"], unique=False)
    op.create_index("manifestlabel_manifest_id", "manifestlabel", ["manifest_id"], unique=False)
    op.create_index(
        "manifestlabel_manifest_id_label_id",
        "manifestlabel",
        ["manifest_id", "label_id"],
        unique=True,
    )
    op.create_index("manifestlabel_repository_id", "manifestlabel", ["repository_id"], unique=False)
    op.create_table(
        "manifestlegacyimage",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("repository_id", sa.Integer(), nullable=False),
        sa.Column("manifest_id", sa.Integer(), nullable=False),
        sa.Column("image_id", sa.Integer(), nullable=False),
        sa.ForeignKeyConstraint(
            ["image_id"], ["image.id"], name=op.f("fk_manifestlegacyimage_image_id_image")
        ),
        sa.ForeignKeyConstraint(
            ["manifest_id"],
            ["manifest.id"],
            name=op.f("fk_manifestlegacyimage_manifest_id_manifest"),
        ),
        sa.ForeignKeyConstraint(
            ["repository_id"],
            ["repository.id"],
            name=op.f("fk_manifestlegacyimage_repository_id_repository"),
        ),
        sa.PrimaryKeyConstraint("id", name=op.f("pk_manifestlegacyimage")),
    )
    op.create_index(
        "manifestlegacyimage_image_id", "manifestlegacyimage", ["image_id"], unique=False
    )
    op.create_index(
        "manifestlegacyimage_manifest_id", "manifestlegacyimage", ["manifest_id"], unique=True
    )
    op.create_index(
        "manifestlegacyimage_repository_id", "manifestlegacyimage", ["repository_id"], unique=False
    )
    op.create_table(
        "tagmanifesttomanifest",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("tag_manifest_id", sa.Integer(), nullable=False),
        sa.Column("manifest_id", sa.Integer(), nullable=False),
        sa.Column("broken", sa.Boolean(), nullable=False, server_default=sa.sql.expression.false()),
        sa.ForeignKeyConstraint(
            ["manifest_id"],
            ["manifest.id"],
            name=op.f("fk_tagmanifesttomanifest_manifest_id_manifest"),
        ),
        sa.ForeignKeyConstraint(
            ["tag_manifest_id"],
            ["tagmanifest.id"],
            name=op.f("fk_tagmanifesttomanifest_tag_manifest_id_tagmanifest"),
        ),
        sa.PrimaryKeyConstraint("id", name=op.f("pk_tagmanifesttomanifest")),
    )
    op.create_index(
        "tagmanifesttomanifest_broken", "tagmanifesttomanifest", ["broken"], unique=False
    )
    op.create_index(
        "tagmanifesttomanifest_manifest_id", "tagmanifesttomanifest", ["manifest_id"], unique=True
    )
    op.create_index(
        "tagmanifesttomanifest_tag_manifest_id",
        "tagmanifesttomanifest",
        ["tag_manifest_id"],
        unique=True,
    )
    op.create_table(
        "tagmanifestlabelmap",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("tag_manifest_id", sa.Integer(), nullable=False),
        sa.Column("manifest_id", sa.Integer(), nullable=True),
        sa.Column("label_id", sa.Integer(), nullable=False),
        sa.Column("tag_manifest_label_id", sa.Integer(), nullable=False),
        sa.Column("manifest_label_id", sa.Integer(), nullable=True),
        sa.Column(
            "broken_manifest",
            sa.Boolean(),
            nullable=False,
            server_default=sa.sql.expression.false(),
        ),
        sa.ForeignKeyConstraint(
            ["label_id"], ["label.id"], name=op.f("fk_tagmanifestlabelmap_label_id_label")
        ),
        sa.ForeignKeyConstraint(
            ["manifest_id"],
            ["manifest.id"],
            name=op.f("fk_tagmanifestlabelmap_manifest_id_manifest"),
        ),
        sa.ForeignKeyConstraint(
            ["manifest_label_id"],
            ["manifestlabel.id"],
            name=op.f("fk_tagmanifestlabelmap_manifest_label_id_manifestlabel"),
        ),
        sa.ForeignKeyConstraint(
            ["tag_manifest_id"],
            ["tagmanifest.id"],
            name=op.f("fk_tagmanifestlabelmap_tag_manifest_id_tagmanifest"),
        ),
        sa.ForeignKeyConstraint(
            ["tag_manifest_label_id"],
            ["tagmanifestlabel.id"],
            name=op.f("fk_tagmanifestlabelmap_tag_manifest_label_id_tagmanifestlabel"),
        ),
        sa.PrimaryKeyConstraint("id", name=op.f("pk_tagmanifestlabelmap")),
    )
    op.create_index(
        "tagmanifestlabelmap_broken_manifest",
        "tagmanifestlabelmap",
        ["broken_manifest"],
        unique=False,
    )
    op.create_index(
        "tagmanifestlabelmap_label_id", "tagmanifestlabelmap", ["label_id"], unique=False
    )
    op.create_index(
        "tagmanifestlabelmap_manifest_id", "tagmanifestlabelmap", ["manifest_id"], unique=False
    )
    op.create_index(
        "tagmanifestlabelmap_manifest_label_id",
        "tagmanifestlabelmap",
        ["manifest_label_id"],
        unique=False,
    )
    op.create_index(
        "tagmanifestlabelmap_tag_manifest_id",
        "tagmanifestlabelmap",
        ["tag_manifest_id"],
        unique=False,
    )
    op.create_index(
        "tagmanifestlabelmap_tag_manifest_label_id",
        "tagmanifestlabelmap",
        ["tag_manifest_label_id"],
        unique=False,
    )
    # ### end Alembic commands ###

    for media_type in DOCKER_SCHEMA1_CONTENT_TYPES:
        op.bulk_insert(
            tables.mediatype,
            [
                {"name": media_type},
            ],
        )

    # ### population of test data ### #
    tester.populate_table(
        "manifest",
        [
            ("digest", tester.TestDataType.String),
            ("manifest_bytes", tester.TestDataType.JSON),
            ("media_type_id", tester.TestDataType.Foreign("mediatype")),
            ("repository_id", tester.TestDataType.Foreign("repository")),
        ],
    )

    tester.populate_table(
        "manifestblob",
        [
            ("manifest_id", tester.TestDataType.Foreign("manifest")),
            ("repository_id", tester.TestDataType.Foreign("repository")),
            ("blob_id", tester.TestDataType.Foreign("imagestorage")),
            ("blob_index", tester.TestDataType.Integer),
        ],
    )

    tester.populate_table(
        "manifestlabel",
        [
            ("manifest_id", tester.TestDataType.Foreign("manifest")),
            ("label_id", tester.TestDataType.Foreign("label")),
            ("repository_id", tester.TestDataType.Foreign("repository")),
        ],
    )

    tester.populate_table(
        "manifestlegacyimage",
        [
            ("manifest_id", tester.TestDataType.Foreign("manifest")),
            ("image_id", tester.TestDataType.Foreign("image")),
            ("repository_id", tester.TestDataType.Foreign("repository")),
        ],
    )

    tester.populate_table(
        "tagmanifesttomanifest",
        [
            ("manifest_id", tester.TestDataType.Foreign("manifest")),
            ("tag_manifest_id", tester.TestDataType.Foreign("tagmanifest")),
        ],
    )

    tester.populate_table(
        "tagmanifestlabelmap",
        [
            ("manifest_id", tester.TestDataType.Foreign("manifest")),
            ("tag_manifest_id", tester.TestDataType.Foreign("tagmanifest")),
            ("tag_manifest_label_id", tester.TestDataType.Foreign("tagmanifestlabel")),
            ("manifest_label_id", tester.TestDataType.Foreign("manifestlabel")),
            ("label_id", tester.TestDataType.Foreign("label")),
        ],
    )

    # ### end population of test data ### #


def downgrade(op, tables, tester):
    for media_type in DOCKER_SCHEMA1_CONTENT_TYPES:
        op.execute(
            tables.mediatype.delete().where(
                tables.mediatype.c.name == op.inline_literal(media_type)
            )
        )

    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table("tagmanifestlabelmap")
    op.drop_table("tagmanifesttomanifest")
    op.drop_table("manifestlegacyimage")
    op.drop_table("manifestlabel")
    op.drop_table("manifestblob")
    op.drop_table("manifest")
    # ### end Alembic commands ###
