import json

import uncloud.secrets as secrets

from xmlrpc.client import ServerProxy as RPCClient

from django.core.management.base import BaseCommand
from xmltodict import parse
from enum import IntEnum
from opennebula.models import VM as VMModel
from uncloud_vm.models import VMHost
from django_auth_ldap.backend import LDAPBackend


class HostStates(IntEnum):
    """
    The following flags are copied from
    https://docs.opennebula.org/5.8/integration/system_interfaces/api.html#schemas-for-host
    """
    INIT = 0  # Initial state for enabled hosts
    MONITORING_MONITORED = 1  # Monitoring the host (from monitored)
    MONITORED = 2  # The host has been successfully monitored
    ERROR = 3  # An error ocurrer while monitoring the host
    DISABLED = 4  # The host is disabled
    MONITORING_ERROR = 5  # Monitoring the host (from error)
    MONITORING_INIT = 6  # Monitoring the host (from init)
    MONITORING_DISABLED = 7  # Monitoring the host (from disabled)
    OFFLINE = 8  # The host is totally offline


class Command(BaseCommand):
    help = 'Syncronize Host information from OpenNebula'

    def add_arguments(self, parser):
        pass

    def handle(self, *args, **options):
        with RPCClient(secrets.OPENNEBULA_URL) as rpc_client:
            success, response, *_ = rpc_client.one.hostpool.info(secrets.OPENNEBULA_USER_PASS)
            if success:
                response = json.loads(json.dumps(parse(response)))
                host_pool = response.get('HOST_POOL', {}).get('HOST', {})
                for host in host_pool:
                    host_share = host.get('HOST_SHARE', {})

                    host_name = host.get('NAME')
                    state = int(host.get('STATE', HostStates.OFFLINE.value))

                    if state == HostStates.MONITORED:
                        status = 'active'
                    elif state == HostStates.DISABLED:
                        status = 'disabled'
                    else:
                        status = 'unusable'

                    usable_cores = host_share.get('TOTAL_CPU')
                    usable_ram_in_kb = int(host_share.get('TOTAL_MEM', 0))
                    usable_ram_in_gb = int(usable_ram_in_kb / 2 ** 20)

                    # vms cannot be created like this -- Nico, 2020-03-17
                    # vms = host.get('VMS', {}) or {}
                    # vms = vms.get('ID', []) or []
                    # vms = ','.join(vms)

                    VMHost.objects.update_or_create(
                        hostname=host_name,
                        defaults={
                            'usable_cores': usable_cores,
                            'usable_ram_in_gb': usable_ram_in_gb,
                            'status': status
                        }
                    )
            else:
                print(response)
