# -*- coding: utf-8 -*-


import hashlib
import requests
from uuid import getnode as get_mac

from django.conf import settings
from django.core import serializers
from django.core.management.base import BaseCommand
from django.core.urlresolvers import reverse

from colorama import Fore
from tendo import singleton

from mtp.apps.common.utils import bypass_orderable
from mtp.apps.sync.hooks import run_pre_sync_hooks, run_post_sync_hooks
from mtp.apps.sync.models import Syncable, Task, Update


def check_hash(file_name, h):
    hash = ""
    try:
        f = open(file_name, 'rb')
        md5 = hashlib.md5()
        while True:
            data = f.read(8192)
            if not data:
                break
            md5.update(data)
        hash = md5.hexdigest()
        f.close()
    except:
        pass

    if hash == h:
        return True
    else:
        return False


class Command(BaseCommand):
    args = ''
    help = 'Update server down. Not launch on global server, only on local.'

    def handle(self, *args, **options):
        me = singleton.SingleInstance()
        if settings.INSTANCE_IS_MASTER:
            return

        print(Fore.GREEN + 'Run pre-sync hooks' + Fore.RESET)
        run_pre_sync_hooks()
        print(Fore.GREEN + '=> DONE!' + Fore.RESET)

        ups = Update.objects.filter(healthy=True)

        updates = serializers.serialize('json', ups, fields=('id',))
        params = {
            'updates_id': updates
        }
        update_down_url = settings.MASTER_INSTANCE_URL + reverse('sync:download')

        response = requests.post(update_down_url, params)

        updates = []

        files_to_sync = []

        with bypass_orderable():  # Keep order from objects in the response

            print((Fore.GREEN + "Data received:" + Fore.RESET))
            for deserialized_object in serializers.deserialize('json', response.text):

                print("%s: %s" % (
                    deserialized_object.object.__class__.__name__,
                    str(deserialized_object.object),
                ))

                if isinstance(deserialized_object.object, Update):
                    obj = deserialized_object.object
                    obj.healthy = False
                    obj.save()
                    updates.append(obj)
                    continue

                else:
                    if isinstance(deserialized_object.object, Syncable):
                        deserialized_object.object.last_update = None
                        deserialized_object.object.update_locally = False
                        files_to_sync = files_to_sync + deserialized_object.object.get_sync_files()

                    deserialized_object.save()

        print((Fore.GREEN + "Files to download:" + Fore.RESET))
        for f in files_to_sync:
            if f['name'] == "":
                continue

            print((f['name']))
            url = settings.MASTER_INSTANCE_URL + \
                settings.MEDIA_URL + f['name'] + "?" + "%d" % (get_mac())
            file_name = settings.MEDIA_ROOT + "/" + f['name']
            if not f['hash']:
                t = Task(path='curl -f -o %s %s' % (file_name, url),
                         finish_path='echo "download"')
                t.save()
            elif not check_hash(file_name, f['hash']):
                t = Task(path='curl -f -o %s %s' % (file_name, url),
                         finish_path='echo "%s  %s" | md5sum -c -' % (f['hash'], file_name))
                t.save()

        print(updates)
        for u in updates:
            u.healthy = True
            u.save()

        print(Fore.GREEN + 'Run post-sync hooks' + Fore.RESET)
        run_post_sync_hooks()
        print(Fore.GREEN + '=> DONE!' + Fore.RESET)
