#!/usr/bin/env python
from __future__ import print_function

import argparse
from sepelib.core import config
from sepelib.mongo.util import register_database

import sys

from walle import dns, network, constants
from walle.clients import dns_api, racktables
from walle.errors import InvalidHostConfiguration, NoInformationError

from walle.hosts import Host


class MockStatboxLogger(object):
    @staticmethod
    def get_child(*args, **kwargs):
        return MockStatboxLogger

    @staticmethod
    def log(*args, **kwargs):
        return None


def proceed(fqdn, clear=False):
    register_database("mongodb")

    host = Host.objects.get(name=fqdn)
    try:
        project = host.get_project(fields=network.DNS_REQUIRED_PROJECT_FIELDS)
        host_vlans = network.get_host_expected_vlans(host, project).vlans
        switch = network.get_current_host_switch_port(host).switch
    except (NoInformationError, InvalidHostConfiguration) as e:
        print("Can not get information: {}".format(e), file=sys.stderr)
        return exit(2)

    active_mac_info = host.get_active_mac()
    if active_mac_info is not None:
        active_mac = active_mac_info.mac
    else:
        print(host, "Unable to determine active MAC address of the host.", file=sys.stderr)
        return exit(3)

    dns_records = None
    fqdns = None
    if clear:
        try:
            fqdns = network.get_host_fqdns(host)
        except InvalidHostConfiguration as e:
            print("Can not get host names: {}".format(e), file=sys.stderr)
            return exit(4)

        try:
            dns_operations = dns.get_delete_operations_for_fqdns(fqdns, MockStatboxLogger)
        except dns_api.DnsError as e:
            print("Error communication with dns api: {}".format(e), file=sys.stderr)
            return exit(5)

    else:
        try:
            dns_records = network.get_host_dns_records(host, project, host.name, switch, active_mac)
        except (InvalidHostConfiguration, network.NoNetworkOnSwitch) as e:
            print("Can not build expected records: {}".format(e), file=sys.stderr)
            return exit(4)

        try:
            dns_operations = dns.get_operations_for_dns_records(dns_records, MockStatboxLogger)
        except dns_api.DnsError as e:
            print("Error communication with dns api: {}".format(e), file=sys.stderr)
            return exit(5)

    print("Host {} #{} from project {}".format(host.name, host.inv, host.project))
    if project.hbf_project_id:
        print("HBF project id: {}".format(hex(project.hbf_project_id)[2:]))

    print("Host expected vlans: {} on switch {}".format(", ".join(map(str, host_vlans)), switch))
    print("Expected networks on the switch:")
    for vlan in host_vlans:
        print(" * {}: {}".format(vlan, ", ".join(racktables.get_vlan_networks(switch, vlan) or [])))

    print("Host active MAC address is {}".format(active_mac))

    if fqdns:
        print("Host fqdns are {}".format(", ".join(fqdns)))

    if dns_records:
        print("Host expected dns records are:")
        for rtype, rname, rdata_set in dns_records:
            print("--- One of:")
            for rdata in rdata_set:
                print("* {} from {} to {}".format(rtype, rname, rdata))
    else:
        print("No dns records expected for the host")

    if dns_operations:
        print("Required dns operations are:")
        for operation in dns_operations:
            print("{} {} from {} to {}".format(operation.operation, operation.type, operation.name, operation.data))
    else:
        print("No operations required")


def _parse_args():
    parser = argparse.ArgumentParser(description="Wall-E dns records and operation debug.")
    parser.add_argument("-c", "--config", required=True, help="configuration file path")
    parser.add_argument("--delete", "--clear", action="store_true",
                        help="Try to check what is needed to be done to delete records.")
    parser.add_argument("hostname", help="Host's FQDN to check dns records for")

    config.augment_args_parser(parser)
    return parser.parse_args()


if __name__ == "__main__":
    args = _parse_args()
    config.load(path=args.config, defaults=constants.DEFAULT_CONFIG_PATH, config_context=args.config_context)

    proceed(args.hostname, args.delete)
