"""card_groups

Revision: 0029
Revision ID: 25e88bf7445c
Revises: 43ed95babe0a
Create Date: 2015-10-26 20:28:04.796807

"""

# revision identifiers, used by Alembic.
revision = '25e88bf7445c'
down_revision = '43ed95babe0a'
branch_labels = None
depends_on = None

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

def upgrade():
    op.create_table('card_group_types',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column('created_at', sa.DateTime(), nullable=True),
        sa.Column('updated_at', sa.DateTime(), nullable=True),
        sa.Column('created_by_id', sa.Integer(), nullable=True),
        sa.Column('owner_id', sa.Integer(), nullable=True),
        sa.Column('name', sa.String(), nullable=True),
        sa.Column('description', sa.Text(), nullable=True),
        sa.Column('scope', sa.Enum('card', 'project', 'org', name='card_group_type_scope'), nullable=False),
        sa.Column('one_group_per_card', sa.Boolean(), nullable=True),
        sa.ForeignKeyConstraint(['created_by_id'], ['users.id'], ondelete='SET NULL'),
        sa.ForeignKeyConstraint(['owner_id'], ['organizations.id'], ondelete='CASCADE'),
        sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_card_group_types_owner_id'), 'card_group_types', ['owner_id'], unique=False)
    op.create_index(op.f('ix_card_group_types_scope'), 'card_group_types', ['scope'], unique=False)

    op.create_table('card_groups',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column('created_at', sa.DateTime(), nullable=True),
        sa.Column('updated_at', sa.DateTime(), nullable=True),
        sa.Column('created_by_id', sa.Integer(), nullable=True),
        sa.Column('group_type_id', sa.Integer(), nullable=True),
        sa.Column('parent_id', sa.Integer(), nullable=True),
        sa.Column('position', sa.Integer(), nullable=True),
        sa.Column('title', sa.String(), nullable=True),
        sa.Column('description', sa.Text(), nullable=True),
        sa.Column('is_archived', sa.Boolean(), nullable=True),
        sa.Column('archived_at', sa.DateTime(), nullable=True),
        sa.Column('meta', sa.PickleType(), nullable=True),
        sa.Column('color', sa.String(), nullable=True),
        sa.Column('icon', sa.String(), nullable=True),
        sa.Column('show_flow_indicator', sa.Boolean(), nullable=True),
        sa.Column('card_state', sa.String(), nullable=True),
        sa.Column('default_card_model_id', sa.Integer(), nullable=True),
        sa.Column('auto_assign_user', sa.String(), nullable=True),
        sa.Column('max_cards_limit', sa.Integer(), nullable=True),
        sa.Column('disallow_direct_card_creation', sa.Boolean(), nullable=True),
        sa.Column('start_date', sa.Date(), nullable=True),
        sa.Column('end_date', sa.Date(), nullable=True),
        sa.Column('milestone_id', sa.Integer(), nullable=True), #temporary
        sa.ForeignKeyConstraint(['created_by_id'], ['users.id'], ondelete='SET NULL'),
        sa.ForeignKeyConstraint(['default_card_model_id'], ['card_models.id'], ondelete='SET NULL'),
        sa.ForeignKeyConstraint(['group_type_id'], ['card_group_types.id'], ondelete='CASCADE'),
        sa.ForeignKeyConstraint(['parent_id'], ['cards.id'], ondelete='CASCADE'),
        sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_card_groups_archived_at'), 'card_groups', ['archived_at'], unique=False)
    op.create_index(op.f('ix_card_groups_group_type_id'), 'card_groups', ['group_type_id'], unique=False)
    op.create_index(op.f('ix_card_groups_is_archived'), 'card_groups', ['is_archived'], unique=False)
    op.create_index(op.f('ix_card_groups_parent_id'), 'card_groups', ['parent_id'], unique=False)
    op.create_index(op.f('ix_card_groups_position'), 'card_groups', ['position'], unique=False)

    op.create_table('card_groups_cards',
        sa.Column('group_id', sa.Integer(), nullable=False),
        sa.Column('card_id', sa.Integer(), nullable=False),
        sa.Column('position', sa.Integer(), nullable=True),
        sa.ForeignKeyConstraint(['card_id'], ['cards.id'], ondelete='CASCADE'),
        sa.ForeignKeyConstraint(['group_id'], ['card_groups.id'], ondelete='CASCADE'),
        sa.PrimaryKeyConstraint('group_id', 'card_id')
    )
    op.create_index(op.f('ix_card_groups_cards_position'), 'card_groups_cards', ['position'], unique=False)

    op.add_column('card_change_history', sa.Column('group_id', sa.Integer(), nullable=True))
    op.add_column('card_change_history', sa.Column('group_title', sa.String(), nullable=True))
    op.create_index(op.f('ix_card_change_history_group_id'), 'card_change_history', ['group_id'], unique=False)
    op.create_foreign_key(None, 'card_change_history', 'card_groups', ['group_id'], ['id'], ondelete='SET NULL')

    op.add_column('cards', sa.Column('archive_because_of_group_id', sa.Integer(), nullable=True))
    op.create_foreign_key(None, 'cards', 'card_groups', ['archive_because_of_group_id'], ['id'], ondelete='SET NULL')

    op.add_column('organizations', sa.Column('default_card_group_type_id', sa.Integer(), nullable=True))
    op.create_foreign_key(None, 'organizations', 'card_group_types', ['default_card_group_type_id'], ['id'], ondelete='SET NULL')

    op.drop_index('ix_card_change_history_list_id', table_name='card_change_history')
    op.drop_constraint('card_change_history_list_id_fkey', 'card_change_history', type_='foreignkey')
    op.drop_constraint('card_models_board_template_id_fkey', 'card_models', type_='foreignkey')
    op.drop_index('ix_cards_done', table_name='cards')
    op.drop_index('ix_cards_done_at', table_name='cards')
    op.drop_index('ix_cards_is_list_archived', table_name='cards')
    op.drop_index('ix_cards_list_id', table_name='cards')
    op.drop_index('ix_cards_list_position', table_name='cards')
    op.drop_index('ix_cards_milestone_id', table_name='cards')
    op.drop_index('ix_cards_reopened', table_name='cards')
    op.drop_constraint('cards_list_id_fkey', 'cards', type_='foreignkey')
    op.drop_constraint('cards_milestone_id_fkey', 'cards', type_='foreignkey')

    op.execute("""
INSERT INTO card_group_types
    (created_at, owner_id, name, scope, one_group_per_card)
SELECT current_timestamp, id, 'Lists', 'card', true FROM organizations;

UPDATE organizations SET default_card_group_type_id = (SELECT id FROM card_group_types WHERE owner_id = organizations.id);

INSERT INTO card_group_types
    (created_at, owner_id, name, scope, one_group_per_card)
SELECT current_timestamp, id, 'Milestones', 'project', true FROM organizations;


INSERT INTO card_groups
    (id, created_at, updated_at, created_by_id, group_type_id, parent_id, position, title,
     description, is_archived, archived_at, meta, color, icon, show_flow_indicator, card_state,
     default_card_model_id, auto_assign_user, max_cards_limit, disallow_direct_card_creation)
SELECT cl.id, cl.created_at, cl.updated_at, cl.created_by_id, (
        SELECT id FROM card_group_types WHERE owner_id = c.owner_id AND name = 'Lists'
     ), cl.parent_id, cl.position, cl.title,
     cl.description, cl.is_archived, cl.archived_at, cl.meta, cl.bgcolor, cl.icon, cl.show_flow_indicator, cl.card_state,
     cl.default_card_model_id, cl.auto_assign_user, cl.max_cards_limit, cl.disallow_direct_card_creation
FROM card_lists cl JOIN cards c ON c.id = cl.parent_id;

SELECT setval('card_groups_id_seq', nextval('card_lists_id_seq'));

INSERT INTO card_groups_cards
    SELECT c.list_id, c.id, c.list_position FROM cards c WHERE c.list_id is not null;


UPDATE card_change_history SET group_id = list_id, group_title = list_title;


INSERT INTO card_groups
    (milestone_id, created_at, updated_at, created_by_id, group_type_id, parent_id, title,
     is_archived, color, start_date, end_date)
SELECT m.id, m.created_at, m.updated_at, m.created_by_id, (
        SELECT id FROM card_group_types WHERE owner_id = c.owner_id AND name = 'Milestones'
     ), m.parent_id, m.title, m.closed, m.color, m.start_date, m.end_date
FROM milestones m JOIN cards c ON c.id = m.parent_id;

INSERT INTO card_groups_cards (group_id, card_id)
    SELECT cg.id, c.id
    FROM cards c JOIN card_groups cg ON cg.milestone_id = c.milestone_id;

WITH positions as (
    SELECT group_id, card_id, row_number() OVER (partition by group_id order by card_id) AS p
    FROM card_groups_cards WHERE position is null
) UPDATE card_groups_cards set position = positions.p - 1 FROM positions
WHERE card_groups_cards.position is null AND positions.group_id = card_groups_cards.group_id
AND positions.card_id = card_groups_cards.card_id;

WITH positions as (
    SELECT group_type_id, id, row_number() OVER (partition by group_type_id order by id) AS p
    FROM card_groups WHERE position is null
) UPDATE card_groups set position = positions.p - 1 FROM positions
WHERE card_groups.position is null AND positions.group_type_id = card_groups.group_type_id
AND positions.id = card_groups.id;
""")


def downgrade():
    op.drop_column('organizations', 'default_card_group_type_id')

    op.create_foreign_key('cards_milestone_id_fkey', 'cards', 'milestones', ['milestone_id'], ['id'])
    op.create_foreign_key('cards_list_id_fkey', 'cards', 'card_lists', ['list_id'], ['id'])
    op.drop_column('cards', 'archive_because_of_group_id')
    op.create_index('ix_cards_reopened', 'cards', ['reopened'], unique=False)
    op.create_index('ix_cards_milestone_id', 'cards', ['milestone_id'], unique=False)
    op.create_index('ix_cards_list_position', 'cards', ['list_position'], unique=False)
    op.create_index('ix_cards_list_id', 'cards', ['list_id'], unique=False)
    op.create_index('ix_cards_is_list_archived', 'cards', ['is_list_archived'], unique=False)
    op.create_index('ix_cards_done_at', 'cards', ['done_at'], unique=False)
    op.create_index('ix_cards_done', 'cards', ['done'], unique=False)

    op.create_foreign_key('card_models_board_template_id_fkey', 'card_models', 'board_templates', ['board_template_id'], ['id'])

    op.create_foreign_key('card_change_history_list_id_fkey', 'card_change_history', 'card_lists', ['list_id'], ['id'])
    op.create_index('ix_card_change_history_list_id', 'card_change_history', ['list_id'], unique=False)
    op.drop_index(op.f('ix_card_change_history_group_id'), table_name='card_change_history')
    op.drop_column('card_change_history', 'group_title')
    op.drop_column('card_change_history', 'group_id')

    op.drop_index(op.f('ix_card_groups_cards_position'), table_name='card_groups_cards')
    op.drop_table('card_groups_cards')

    op.drop_index(op.f('ix_card_groups_position'), table_name='card_groups')
    op.drop_index(op.f('ix_card_groups_parent_id'), table_name='card_groups')
    op.drop_index(op.f('ix_card_groups_is_archived'), table_name='card_groups')
    op.drop_index(op.f('ix_card_groups_group_type_id'), table_name='card_groups')
    op.drop_index(op.f('ix_card_groups_archived_at'), table_name='card_groups')
    op.drop_table('card_groups')

    op.drop_index(op.f('ix_card_group_types_scope'), table_name='card_group_types')
    op.drop_index(op.f('ix_card_group_types_owner_id'), table_name='card_group_types')
    op.drop_table('card_group_types')
