"""org attributes to project

Revision: 0073
Revision ID: 1b3bcd25ba75
Revises: 44182012460b
Create Date: 2016-09-08 11:11:30.503130

"""

# revision identifiers, used by Alembic.
revision = '1b3bcd25ba75'
down_revision = '44182012460b'
branch_labels = None
depends_on = None

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
import uuid

organizations = sa.Table(
    'organizations',
    sa.MetaData(),
    sa.Column('id', sa.Integer, primary_key=True),
    sa.Column('attribute_group_id', sa.Integer),
)

projects = sa.Table(
    'projects',
    sa.MetaData(),
    sa.Column('id', sa.Integer, primary_key=True),
    sa.Column('owner_id', sa.Integer),
    sa.Column('attribute_group_id', sa.Integer),
    sa.Column('top_level_card_id', sa.Integer)
)

attribute_groups = sa.Table(
    'attribute_groups',
    sa.MetaData(),
    sa.Column('id', sa.Integer, primary_key=True),
    sa.Column('owner_id', sa.Integer)
)

attributes = sa.Table(
    'attributes',
    sa.MetaData(),
    sa.Column('id', sa.Integer, primary_key=True),
    sa.Column('card_model_id', sa.Integer),
    sa.Column('card_id', sa.Integer),
    sa.Column('name', sa.String),
    sa.Column('description', sa.Text),
    sa.Column('type_name', sa.String),
    sa.Column('container', sa.String),
    sa.Column('position', sa.Integer),
    sa.Column('options', sa.PickleType),
    sa.Column('default_value', sa.PickleType),
    sa.Column('is_from_builtin', sa.Boolean),
    sa.Column('show_on_tile', sa.Boolean),
    sa.Column('group_id', sa.Integer)
)

card_attributes = sa.Table(
    'card_attributes',
    sa.MetaData(),
    sa.Column('id', sa.Integer, primary_key=True),
    sa.Column('attribute_id', sa.Integer),
    sa.Column('card_id', sa.Integer)
)

cards = sa.Table(
    'cards',
    sa.MetaData(),
    sa.Column('id', sa.Integer, primary_key=True),
    sa.Column('project_id', sa.Integer)
)

group_types = sa.Table(
    'card_group_types',
    sa.MetaData(),
    sa.Column('id', sa.Integer, primary_key=True),
    sa.Column('owner_id', sa.Integer),
    sa.Column('name', sa.String),
    sa.Column('singular_name', sa.String),
    sa.Column('plural_name', sa.String),
    sa.Column('scope', sa.String),
    sa.Column('one_group_per_card', sa.Boolean),
    sa.Column('display_on_card', sa.String),
    sa.Column('auto_random_color', sa.Boolean),
    sa.Column('builtin', sa.String),
    sa.Column('auto_enabled_on_new_projects', sa.Boolean),
    sa.Column('is_project_specific', sa.Boolean),
    sa.Column('created_by_id', sa.Integer),
    sa.Column('created_at', sa.DateTime),
    sa.Column('updated_at', sa.DateTime),
    sa.Column('icon', sa.String),
    sa.Column('description', sa.Text),
    sa.Column('cache_id', sa.String),
    sa.Column('attribute_id', sa.Integer)
)

card_groups = sa.Table(
    'card_groups',
    sa.MetaData(),
    sa.Column('id', sa.Integer, primary_key=True),
    sa.Column('parent_id', sa.Integer),
    sa.Column('group_type_id', sa.Integer)
)


def upgrade():
    conn = op.get_bind()
    gt_to_delete = []
    attr_to_delete = []
    for org in conn.execute(organizations.select()):
        attributes_group = conn.execute(attribute_groups.select().where(attribute_groups.c.id == org.attribute_group_id)).first()
        if not attributes_group:
            continue
        attr_to_delete.append({'group_id': attributes_group.id})
        for project in conn.execute(projects.select().where(projects.c.owner_id == org.id)):
            for attribute in conn.execute(attributes.select().where(attributes.c.group_id == attributes_group.id)):

                has_value = attribute.type_name != 'group_type' or False
                gt = conn.execute(group_types.select().where(group_types.c.attribute_id == attribute.id)).first()
                if not has_value and gt is not None:
                    gt_to_delete.append({'gt_id': gt.id})
                    for info in conn.execute(card_groups.join(cards, card_groups.c.parent_id==cards.c.id).select().where(sa.and_(card_groups.c.group_type_id==gt.id, cards.c.project_id==project.id))):
                        has_value = True
                        break

                if not has_value:
                    continue

                r = conn.execute(attributes.insert().values(
                    card_model_id=None,
                    card_id=attribute.card_id,
                    name=attribute.name,
                    description=attribute.description,
                    type_name=attribute.type_name,
                    container=attribute.container,
                    position=attribute.position,
                    options=attribute.options,
                    default_value=attribute.default_value,
                    is_from_builtin=attribute.is_from_builtin,
                    show_on_tile=attribute.show_on_tile,
                    group_id=project.attribute_group_id
                ))
                attribute_id = r.inserted_primary_key[0]

                if gt is not None:
                    r = conn.execute(group_types.insert().values(
                        owner_id=gt.owner_id,
                        name=gt.name,
                        singular_name=gt.singular_name,
                        plural_name=gt.plural_name,
                        scope=gt.scope,
                        one_group_per_card=gt.one_group_per_card,
                        display_on_card=gt.display_on_card,
                        auto_random_color=gt.auto_random_color,
                        created_by_id=gt.created_by_id,
                        created_at=gt.created_at,
                        updated_at=gt.updated_at,
                        icon=gt.icon,
                        description=gt.description,
                        builtin=gt.builtin,
                        attribute_id=attribute_id,
                        cache_id=uuid.uuid4(),
                        auto_enabled_on_new_projects=False,
                        is_project_specific=True
                    ))
                    gt_id = r.inserted_primary_key[0]
                    attribute.options['group_type'] = gt_id
                    conn.execute(attributes.update().where(attributes.c.id == attribute_id).values(
                        options = attribute.options
                    ))
                    conn.execute(card_groups.update().where(sa.and_(card_groups.c.group_type_id == gt.id, card_groups.c.parent_id == project.top_level_card_id)).values(
                        group_type_id = gt_id
                    ))
                for value in conn.execute(card_attributes.select().where(card_attributes.c.attribute_id == attribute.id)):
                    card = conn.execute(cards.select().where(cards.c.id == value.card_id)).first()
                    if card.project_id != project.id:
                        continue
                    conn.execute(card_attributes.update().where(card_attributes.c.id == value.id).values(
                        attribute_id = attribute_id
                    ))

    if attr_to_delete:
        stmt = attributes.delete().where(attributes.c.group_id == sa.bindparam('group_id'))
        conn.execute(stmt, attr_to_delete)
    if gt_to_delete:
        stmt = group_types.delete().where(group_types.c.id == sa.bindparam('gt_id'))
        conn.execute(stmt, gt_to_delete)


def downgrade():
    pass
