# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2017-02-27 17:03

import os
from typing import Text

import requests
from boto.s3.bucket import Bucket
from boto.s3.connection import S3Connection
from boto.s3.key import Key
from django.conf import settings
from django.core.files.uploadedfile import SimpleUploadedFile
from django.db import migrations
from django.db.backends.postgresql_psycopg2.schema import DatabaseSchemaEditor
from django.db.migrations.state import StateApps

from zerver.lib.avatar_hash import user_avatar_hash, user_avatar_path

def mkdirs(path: Text) -> None:
    dirname = os.path.dirname(path)
    if not os.path.isdir(dirname):
        os.makedirs(dirname)

class MissingAvatarException(Exception):
    pass

def move_local_file(type: Text, path_src: Text, path_dst: Text) -> None:
    src_file_path = os.path.join(settings.LOCAL_UPLOADS_DIR, type, path_src)
    dst_file_path = os.path.join(settings.LOCAL_UPLOADS_DIR, type, path_dst)
    if os.path.exists(dst_file_path):
        return
    if not os.path.exists(src_file_path):
        # This is likely caused by a user having previously changed their email
        raise MissingAvatarException()
        return
    mkdirs(dst_file_path)
    os.rename(src_file_path, dst_file_path)

def move_avatars_to_be_uid_based(apps: StateApps, schema_editor: DatabaseSchemaEditor) -> None:
    user_profile_model = apps.get_model('zerver', 'UserProfile')
    if settings.LOCAL_UPLOADS_DIR is not None:
        for user_profile in user_profile_model.objects.filter(avatar_source="U"):
            src_file_name = user_avatar_hash(user_profile.email)
            dst_file_name = user_avatar_path(user_profile)
            try:
                move_local_file('avatars', src_file_name + '.original', dst_file_name + '.original')
                move_local_file('avatars', src_file_name + '-medium.png', dst_file_name + '-medium.png')
                move_local_file('avatars', src_file_name + '.png', dst_file_name + '.png')
            except MissingAvatarException:
                # If the user's avatar is missing, it's probably
                # because they previously changed their email address.
                # So set them to have a gravatar instead.
                user_profile.avatar_source = "G"
                user_profile.save(update_fields=["avatar_source"])
    else:
        conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY)
        bucket_name = settings.S3_AVATAR_BUCKET
        bucket = conn.get_bucket(bucket_name, validate=False)
        for user_profile in user_profile_model.objects.filter(avatar_source="U"):
            uid_hash_path = user_avatar_path(user_profile)
            email_hash_path = user_avatar_hash(user_profile.email)
            if bucket.get_key(uid_hash_path):
                continue
            if not bucket.get_key(email_hash_path):
                # This is likely caused by a user having previously changed their email
                # If the user's avatar is missing, it's probably
                # because they previously changed their email address.
                # So set them to have a gravatar instead.
                user_profile.avatar_source = "G"
                user_profile.save(update_fields=["avatar_source"])
                continue

            bucket.copy_key(uid_hash_path + ".original",
                            bucket_name,
                            email_hash_path + ".original")
            bucket.copy_key(uid_hash_path + "-medium.png",
                            bucket_name,
                            email_hash_path + "-medium.png")
            bucket.copy_key(uid_hash_path,
                            bucket_name,
                            email_hash_path)

        # From an error handling sanity perspective, it's best to
        # start deleting after everything is copied, so that recovery
        # from failures is easy (just rerun one loop or the other).
        for user_profile in user_profile_model.objects.filter(avatar_source="U"):
            bucket.delete_key(user_avatar_hash(user_profile.email) + ".original")
            bucket.delete_key(user_avatar_hash(user_profile.email) + "-medium.png")
            bucket.delete_key(user_avatar_hash(user_profile.email))

class Migration(migrations.Migration):

    dependencies = [
        ('zerver', '0059_userprofile_quota'),
    ]

    operations = [
        migrations.RunPython(move_avatars_to_be_uid_based)
    ]
