"""activities

Revision: 0062
Revision ID: 3ab6d84b6186
Revises: bfc8eb1f8c2
Create Date: 2016-06-21 16:53:01.468562

"""

# revision identifiers, used by Alembic.
revision = '3ab6d84b6186'
down_revision = 'bfc8eb1f8c2'
branch_labels = None
depends_on = None

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


activities_table = sa.Table(
    'activities',
    sa.MetaData(),
    sa.Column('id', sa.Integer, primary_key=True),
    sa.Column('subject_value', sa.PickleType()),
    sa.Column('sub_object_value', postgresql.JSON()),
)


def upgrade():
    op.execute("DROP VIEW IF EXISTS metrics_project_active_months");
    op.execute("DROP VIEW IF EXISTS metrics_user_active_months");

    op.create_table('card_comments',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column('card_id', sa.Integer(), nullable=True),
        sa.Column('created_by_id', sa.Integer(), nullable=True),
        sa.Column('created_at', sa.DateTime(), nullable=True),
        sa.Column('updated_at', sa.DateTime(), nullable=True),
        sa.Column('message', sa.Text(), nullable=True),
        sa.Column('is_pinned', sa.Boolean(), nullable=True),
        sa.Column('stream_id', sa.Integer(), nullable=True),
        sa.ForeignKeyConstraint(['card_id'], ['cards.id'], ondelete='CASCADE'),
        sa.ForeignKeyConstraint(['created_by_id'], ['users.id'], ondelete='SET NULL'),
        sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_card_comments_card_id'), 'card_comments', ['card_id'], unique=False)
    op.create_index(op.f('ix_card_comments_created_by_id'), 'card_comments', ['created_by_id'], unique=False)

    op.execute("""INSERT INTO card_comments (card_id, created_by_id, created_at, message, is_pinned, stream_id)
        SELECT card_id, created_by_id, created_at, message, is_pinned, id FROM stream WHERE item_type = 'comment'""")

    op.rename_table('stream', 'activities')
    op.add_column('activities', sa.Column('owner_id', sa.Integer(), nullable=True))
    op.add_column('activities', sa.Column('verb', sa.String(), nullable=True))
    op.add_column('activities', sa.Column('object_type', sa.String(), index=True))
    op.add_column('activities', sa.Column('object_id', sa.Integer(), index=True))
    op.add_column('activities', sa.Column('object_value', postgresql.JSON()))
    op.add_column('activities', sa.Column('sub_object_type', sa.String(), index=True))
    op.add_column('activities', sa.Column('sub_object_id', sa.Integer(), index=True))
    op.add_column('activities', sa.Column('sub_object_value', postgresql.JSON()))
    op.add_column('activities', sa.Column('origin_type', sa.String(), index=True))
    op.add_column('activities', sa.Column('origin_id', sa.Integer(), index=True))
    op.add_column('activities', sa.Column('origin_value', postgresql.JSON()))
    op.add_column('activities', sa.Column('target_type', sa.String(), index=True))
    op.add_column('activities', sa.Column('target_id', sa.Integer(), index=True))
    op.add_column('activities', sa.Column('target_value', postgresql.JSON()))

    op.create_foreign_key(None, 'activities', 'organizations', ['owner_id'], ['id'], ondelete='CASCADE')

    conn = op.get_bind()
    for item in conn.execute(activities_table.select().where(activities_table.c.subject_value!=None)):
        conn.execute(activities_table.update().where(activities_table.c.id==item.id).values(sub_object_value=item.subject_value))

    op.execute("""UPDATE activities SET verb = upper(label), sub_object_type = subject_type, sub_object_id = subject_id,
        owner_id = (SELECT owner_id FROM cards WHERE id = card_id), object_type='Card', object_id=card_id,
        object_value = (SELECT to_json(title) FROM cards WHERE id = card_id)""")

    op.execute("""UPDATE activities SET verb = 'CREATE', target_type = 'Card', target_id = object_id, target_value = object_value,
        object_type = 'CardComment', object_id = (SELECT id FROM card_comments WHERE stream_id = activities.id), object_value = to_json(message),
        message = '{actor} left a comment on {target}',
        sub_object_type = null, sub_object_id = null, sub_object_value = null
        WHERE item_type = 'comment'""")

    op.execute("""UPDATE activities SET verb = 'UPDATE', message = '{actor} attached {sub_object} to {target}',
        sub_object_type = 'CardFile', target_type = 'Card', target_id = object_id, target_value = object_value,
        object_type = 'CardModelAttribute', object_id = null, object_value = to_json('attachments'::text) WHERE label = 'file'""")

    op.execute("""UPDATE activities SET verb = 'UPDATE', message = '{actor} assigned {sub_object} to {target}',
        sub_object_type = 'User', target_type = 'Card', target_id = object_id, target_value = object_value,
        object_type = 'CardModelAttribute', object_id = null, object_value = to_json('assignees'::text) WHERE label = 'assigned'""")

    op.execute("""UPDATE activities SET verb = 'UPDATE', message = '{actor} unassigned {sub_object} from {target}',
        sub_object_type = 'User', target_type = 'Card', target_id = object_id, target_value = object_value,
        object_type = 'CardModelAttribute', object_id = null, object_value = to_json('assignees'::text) WHERE label = 'unassigned'""")

    op.execute("""UPDATE activities SET verb = 'ADD', message = replace(replace(message, '{subject}', '{object}'), '{user}', '{actor}'),
        target_type = 'Card', target_id = object_id, target_value = object_value,
        object_type = 'commit', object_id = null, object_value = sub_object_value,
        sub_object_type = null, sub_object_id = null, sub_object_value = null
        WHERE label = 'commit'""")

    op.execute("""UPDATE activities SET verb = 'JOIN', message = '{actor} joined {object}' WHERE label = 'joined'""")

    op.execute("""UPDATE activities SET verb = 'LEFT', message = '{actor} left {object}'
        WHERE label = 'left' AND message = '{user} has left'""")

    op.execute("""UPDATE activities SET verb = 'LEFT', message = '{actor} removed {sub_object} from members of {object}'
        WHERE label = 'left' AND message = '{user} removed {subject} from members'""")

    op.execute("""UPDATE activities SET verb = 'CREATE', message = '{actor} created {object} under {target}',
        target_type = 'Card', target_id = object_id, target_value = object_value,
        object_type = 'CardGroup', object_id = sub_object_id, object_value = sub_object_value,
        sub_object_type = null, sub_object_id = null, sub_object_value = null
        WHERE label = 'group_created'""")

    op.execute("""UPDATE activities SET verb = 'UPDATE', message = '{actor} changed the title from {origin}',
        origin_value = sub_object_value, sub_object_type = null, sub_object_id = null, sub_object_value = null
        WHERE label = 'updated' and message = '{user} changed the title from {subject}'""")

    op.execute("""UPDATE activities SET verb = 'UPDATE', message = '{actor} changed the background color',
        sub_object_type = null, sub_object_id = null, sub_object_value = null
        WHERE label = 'updated' and message = '{user} changed the background color'""")

    op.execute("""UPDATE activities SET verb = 'UPDATE', message = '{actor} changed the state of {object} to {target}',
        target_value = sub_object_value, sub_object_type = null, sub_object_id = null, sub_object_value = null
        WHERE label = 'updated' and message = '{user} changed the state of the card to {subject}'""")

    op.execute("""UPDATE activities SET verb = 'UPDATE', message = '{actor} switched the model of {object} to {target}',
        target_type = sub_object_type, target_id = sub_object_id, target_value = sub_object_value,
        sub_object_type = null, sub_object_id = null, sub_object_value = null
        WHERE label = 'updated' and message = '{user} switched the model to {subject}'""")

    op.execute("""UPDATE activities SET verb = 'MOVE', message = '{actor} moved {object} to {target}',
        target_type = sub_object_type, target_id = sub_object_id, target_value = sub_object_value,
        sub_object_type = null, sub_object_id = null, sub_object_value = null
        WHERE label = 'moved' and message = '{user} moved {target} to {subject}'""")

    op.execute("""UPDATE activities SET verb = 'MOVE', message = '{actor} moved {object} to a board under a different project'
        WHERE label = 'moved' and message = '{user} moved {target} to a board under a different project'""")

    op.execute("""UPDATE activities SET verb = 'COPY', message = '{actor} created {object} as a copy'
        WHERE label = 'copied' and message = '{user} copied {target} to {subject}'""")

    op.execute("""UPDATE activities SET verb = 'MOVE', message = '{actor} converted {object} to a project'
        WHERE label = 'moved' and message = '{user} converted {target} to a project'""")

    op.execute("""UPDATE activities SET verb = 'ARCHIVE', message = '{actor} archived {object}'
        WHERE label = 'archived' and message = '{user} archived {target}'""")

    op.execute("""UPDATE activities SET verb = 'RESTORE', message = '{actor} restored {object}'
        WHERE label = 'restored'""")

    op.execute("""UPDATE activities SET verb = 'CREATE', message = '{actor} created {object}'
        WHERE label = 'created' and message = '{user} added {target}'""")

    op.execute("""DELETE FROM activities WHERE label = 'created' and message = '{user} linked to {subject}'""")
    op.execute("""DELETE FROM activities WHERE label = 'created' and message = '{user} created {subject}' and sub_object_type = 'Card'""")

    op.execute("""UPDATE activities SET verb = 'UPDATE', message = '{actor} changed the background color of {object}',
        object_type = 'CardGroup', object_id = sub_object_id, object_value = sub_object_value,
        sub_object_type = null, sub_object_id = null, sub_object_value = null
        WHERE label = 'group_updated' and message = '{user} changed the background color of group {subject}'""")

    op.execute("""DELETE FROM activities WHERE label = 'group_updated' and message = '{user} renamed group {title} to {subject}'""")

    op.execute("""UPDATE activities SET verb = 'ARCHIVE', message = '{actor} archived {object}',
        object_type = 'CardGroup', object_id = sub_object_id, object_value = sub_object_value,
        sub_object_type = null, sub_object_id = null, sub_object_value = null
        WHERE label = 'group_archived'""")

    op.execute("""UPDATE activities SET verb = 'RESTORE', message = '{actor} restored {object}',
        object_type = 'CardGroup', object_id = sub_object_id, object_value = sub_object_value,
        sub_object_type = null, sub_object_id = null, sub_object_value = null
        WHERE label = 'group_restored'""")

    op.execute("""UPDATE activities SET message = replace(replace(replace(message, '{target}', '{object}'), '{subject}', '{sub_object}'), '{user}', '{actor}')
        WHERE message like '{user}%'""")
    op.execute("UPDATE activities SET verb = 'CREATE' WHERE verb = 'CREATED'")
    op.execute("UPDATE activities SET verb = 'UPDATE' WHERE verb = 'UPDATED'")
    op.execute("UPDATE activities SET verb = 'COPY' WHERE verb = 'COPIED'")
    op.execute("UPDATE activities SET verb = 'MOVE' WHERE verb = 'MOVED'")
    op.execute("UPDATE activities SET verb = 'RESTORE' WHERE verb = 'RESTORED'")
    op.execute("UPDATE activities SET verb = 'CREATE' WHERE verb = 'LIST_CREATED'")
    op.execute("UPDATE activities SET verb = 'UPDATE' WHERE verb = 'LIST_UPDATED'")
    op.execute("UPDATE activities SET verb = 'ARCHIVE' WHERE verb = 'LIST_ARCHIVED'")
    op.execute("UPDATE activities SET verb = 'RESTORE' WHERE verb = 'LIST_RESTORED'")
    op.execute("UPDATE activities SET message = '{actor} created {sub_object}' WHERE message = '{actor} created {sub_object} in list {list}'")
    op.execute("DELETE FROM activities WHERE message = '{actor} renamed list {title} to {sub_object}'")

    op.create_index(op.f('ix_activities_owner_id'), 'activities', ['owner_id'], unique=False)
    op.create_index(op.f('ix_activities_created_at'), 'activities', ['created_at'], unique=False)

    op.drop_constraint('stream_card_id_fkey', 'activities')
    op.drop_index(op.f('ix_stream_card_id'), table_name='activities')
    op.drop_index(op.f('ix_stream_is_pinned'), table_name='activities')
    op.drop_index(op.f('ix_stream_item_type'), table_name='activities')
    op.drop_column('activities', 'subject_type')
    op.drop_column('activities', 'subject_id')
    op.drop_column('activities', 'subject_value')
    op.drop_column('activities', 'args')
    op.drop_column('activities', 'label')
    op.drop_column('activities', 'card_id')
    op.drop_column('activities', 'item_type')
    op.drop_column('activities', 'is_pinned')

    op.drop_column('card_comments', 'stream_id')


def downgrade():
    pass
