# -*- coding: utf-8 -*-
# Generated by Django 1.11.13 on 2018-05-08 08:32
from __future__ import unicode_literals

import math

from django.core.management.color import no_style
from django.db import migrations


def migrate_users(apps, schema_editor):
    migrate_table(
        schema_editor,
        (
            'id', 'password', 'last_login', 'is_superuser', 'first_name',
            'email', 'is_active', 'date_joined', 'username',
        ),
        (
            'id', 'password', 'last_login', 'is_superuser', 'full_name',
            'email', 'is_active', 'date_joined', 'username',
        ),
        'auth_user',
        'weblate_auth_user',
        apps.get_model('weblate_auth', 'User')
    )


def migrate_groups(apps, schema_editor):
    migrate_table(
        schema_editor,
        ('id', 'name'),
        ('id', 'name', 'project_selection', 'language_selection', 'internal'),
        'auth_group',
        'weblate_auth_group',
        apps.get_model('weblate_auth', 'Group'),
        (0, 1, False),
    )

def migrate_user_groups(apps, schema_editor):
    migrate_table(
        schema_editor,
        ('id', 'user_id', 'group_id'),
        ('id', 'user_id', 'group_id'),
        'auth_user_groups',
        'weblate_auth_user_groups',
        apps.get_model('weblate_auth', 'User').groups.through,
    )


def migrate_table(schema_editor, old_cols, new_cols, from_table_name, to_table_name, to_model, extra=()):
    # Avoid migration on fresh installs which won't get users table
    if from_table_name not in schema_editor.connection.introspection.table_names():
        return

    max_id = get_max_id(schema_editor, from_table_name)

    # Use batches to avoid loading entire table into memory
    BATCH_SIZE = 100

    # Careful with off-by-one errors where max_id is a multiple of BATCH_SIZE
    for batch_num in range(0, int(math.floor(max_id / BATCH_SIZE)) + 1):
        start = batch_num * BATCH_SIZE
        stop = start + BATCH_SIZE
        ops = schema_editor.connection.ops
        cursor = schema_editor.connection.cursor()
        columns_sql = ", ".join(ops.quote_name(col_name) for col_name in old_cols)
        cursor.execute(
            "SELECT {1} FROM {0} WHERE id >= %s AND id < %s;".format(
                ops.quote_name(from_table_name),
                columns_sql,
            ),
            [start, stop]
        )

        for row in cursor.fetchall():
            values_sql = ", ".join(["%s"] * len(new_cols))
            columns_sql = ", ".join(ops.quote_name(col_name) for col_name in new_cols)
            sql = "INSERT INTO {0} ({1}) VALUES ({2});".format(
                ops.quote_name(to_table_name),
                columns_sql,
                values_sql
            )

            # could collect and do 'executemany', but sqlite doesn't let us
            # execute more than one statement at once it seems.
            schema_editor.connection.cursor().execute(sql, row + extra)
    if to_model:
        reset_seq = schema_editor.connection.ops.sequence_reset_sql(
            no_style(),
            [to_model],
        )
        for sql in reset_seq:
            schema_editor.connection.cursor().execute(sql)


def get_max_id(schema_editor, table_name):
    cursor = schema_editor.connection.cursor()
    cursor.execute("SELECT MAX(id) FROM {0};".format(table_name), [])
    max_id = cursor.fetchall()[0][0]
    if max_id is None:
        max_id = 0
    return max_id


class Migration(migrations.Migration):

    dependencies = [
        ('weblate_auth', '0003_permissions'),
        ('auth', '0008_alter_user_username_max_length'),
    ]

    operations = [
        migrations.RunPython(migrate_users),
        migrations.RunPython(migrate_groups),
        migrations.RunPython(migrate_user_groups),
    ]
