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

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),
    ]

Make sure tags/attributes are converted correctly