# -*- coding: utf-8 -*-
# Generated by Django 1.11.3 on 2017-07-09 21:33


import re

from django.db import migrations

CASE_WORD_EXCEPTIONS = []


def _case_sensitive_replace(string, old, new):
    """
    Replace text, retaining exact case.

    Args:
        string (str): String in which to perform replacement.
        old (str): Word or substring to replace.
        new (str): What to replace `old` with.

    Returns:
        repl_string (str): Version of string where instances of
            `old` has been replaced with `new`, retaining case.

    """

    def repl(match):
        current = match.group()
        # treat multi-word sentences word-by-word
        old_words = current.split(" ")
        new_words = new.split(" ")
        out = []
        for old_word, new_word in zip(old_words, new_words):
            result = []
            all_upper = True
            for ind, chr in enumerate(old_word):
                if ind >= len(new):
                    break
                if chr.isupper():
                    result.append(new_word[ind].upper())
                else:
                    result.append(new_word[ind].lower())
                    all_upper = False
            # special cases - keep remaing case)
            if new_word.lower() in CASE_WORD_EXCEPTIONS:
                result.append(new_word[ind + 1 :])
            # append any remaining characters from new
            elif all_upper:
                result.append(new_word[ind + 1 :].upper())
            else:
                result.append(new_word[ind + 1 :].lower())
            out.append("".join(result))
        # if we have more new words than old ones, just add them verbatim
        out.extend([new_word for ind, new_word in enumerate(new_words) if ind >= len(old_words)])
        return " ".join(out)

    if string is None:
        return None

    regex = re.compile(re.escape(old), re.I)
    return regex.sub(repl, string)


def update_typeclasses(apps, schema_editor):

    ObjectDB = apps.get_model("objects", "ObjectDB")
    AccountDB = apps.get_model("accounts", "AccountDB")
    ScriptDB = apps.get_model("scripts", "ScriptDB")
    ChannelDB = apps.get_model("comms", "ChannelDB")
    Attributes = apps.get_model("typeclasses", "Attribute")
    Tags = apps.get_model("typeclasses", "Tag")

    for obj in ObjectDB.objects.all():
        obj.db_typeclass_path = _case_sensitive_replace(obj.db_typeclass_path, "player", "account")
        obj.db_cmdset_storage = _case_sensitive_replace(obj.db_cmdset_storage, "player", "account")
        obj.db_lock_storage = _case_sensitive_replace(obj.db_lock_storage, "player", "account")
        obj.save(update_fields=["db_typeclass_path", "db_cmdset_storage", "db_lock_storage"])
    for obj in AccountDB.objects.all():
        obj.db_typeclass_path = _case_sensitive_replace(obj.db_typeclass_path, "player", "account")
        obj.db_cmdset_storage = _case_sensitive_replace(obj.db_cmdset_storage, "player", "account")
        obj.db_lock_storage = _case_sensitive_replace(obj.db_lock_storage, "player", "account")
        obj.save(update_fields=["db_typeclass_path", "db_cmdset_storage", "db_lock_storage"])
    for obj in ScriptDB.objects.all():
        obj.db_typeclass_path = _case_sensitive_replace(obj.db_typeclass_path, "player", "account")
        obj.db_lock_storage = _case_sensitive_replace(obj.db_lock_storage, "player", "account")
        obj.save(update_fields=["db_typeclass_path", "db_lock_storage"])
    for obj in ChannelDB.objects.all():
        obj.db_typeclass_path = _case_sensitive_replace(obj.db_typeclass_path, "player", "account")
        obj.db_lock_storage = _case_sensitive_replace(obj.db_lock_storage, "player", "account")
        obj.save(update_fields=["db_typeclass_path", "db_lock_storage"])
    for obj in Attributes.objects.filter(db_model="playerdb"):
        obj.db_model = "accountdb"
        obj.save(update_fields=["db_model"])
    for obj in Tags.objects.filter(db_model="playerdb"):
        obj.db_model = "accountdb"
        obj.save(update_fields=["db_model"])


class Migration(migrations.Migration):

    dependencies = [("typeclasses", "0008_lock_and_perm_rename")]

    operations = [migrations.RunPython(update_typeclasses)]
