import json
from operator import itemgetter

import requests

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

from waffle.models import Switch


class Command(BaseCommand):
    """Management command to replace all waffle data with data from the master.

    It currently only synchronizes switches.
    All switches from the local database are dropped before being replaced by data
    from the master.

    """

    help = "Replace waffle switches with ones from the master instance."

    def handle(self, *args, **options):
        # Get waffle data from the master.
        download_waffle_url = settings.MASTER_INSTANCE_URL + reverse('sync:download_waffle')
        post_data = {
            'download-waffle': 1
        }
        response = requests.post(download_waffle_url, post_data)

        # Deserialize data from response.
        data = serializers.deserialize('json',
            json.loads(
                response.content.decode('utf-8')
            )['waffle']['switch']
        )

        # Clear all existing switches.
        existing = Switch.objects.all()
        existing_switches = {s.name: s.active for s in existing}
        existing.delete()

        # Insert switches we got from the master.
        new_switches = set()
        for switch_holder in data:

            # Save the switch.
            switch = switch_holder.object
            switch.save()

            # Add in the new switches to compute later which ones are really new.
            new_switches.add(switch.name)

            # Print information about the state of this switch.
            if switch.name in existing_switches:
                if switch.active == existing_switches[switch.name]:
                    text = 'still'
                else:
                    text = 'now'
            else:
                text = 'new and is'

            self.stdout.write('Switch "%s" is %s %s' % (
                switch.name,
                text,
                'active' if switch.active else 'NOT active'
            ))

        # Print information about removed switches.
        for name, active in sorted(existing_switches.items(), key=itemgetter(0)):
            if name not in new_switches:
                self.stdout.write('Switch "%s" (%s) was removed' % (
                    name,
                    'active' if active else 'NOT active'
                ))

        # Print final information about global state.
        if not existing_switches:
            self.stdout.write('Note: no switches existed before')
        if not new_switches:
            self.stdout.write('Note: no switches retrieved from master')
