#
# Copyright 2017 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""
Some consul related convenience functions
"""

from __future__ import absolute_import
from structlog import get_logger
from consul import Consul
from random import randint
from .nethelpers import get_my_primary_local_ipv4
from six.moves import range

log = get_logger()


def connect_to_consult(consul_endpoint):
    log.debug('getting-service-endpoint', consul=consul_endpoint)

    host = consul_endpoint.split(':')[0].strip()
    port = int(consul_endpoint.split(':')[1].strip())

    return Consul(host=host, port=port)


def verify_all_services_healthy(consul_endpoint, service_name=None,
                                number_of_expected_services=None):
    """
    Verify in consul if any service is healthy
    :param consul_endpoint: a <host>:<port> string
    :param service_name: name of service to check, optional
    :param number_of_expected_services number of services to check for, optional
    :return: true if healthy, false otherwise
    """

    def check_health(service):
        _, serv_health = consul.health.service(service, passing=True)
        return not serv_health == []

    consul = connect_to_consult(consul_endpoint)

    if service_name is not None:
        return check_health(service_name)

    services = get_all_services(consul_endpoint)

    items = list(services.keys())

    if number_of_expected_services is not None and \
                    len(items) != number_of_expected_services:
        return False

    for item in items:
        if not check_health(item):
            return False

    return True


def get_all_services(consul_endpoint):
    log.debug('getting-service-verify-health')

    consul = connect_to_consult(consul_endpoint)
    _, services = consul.catalog.services()

    return services


def get_all_instances_of_service(consul_endpoint, service_name):
    log.debug('getting-all-instances-of-service', service=service_name)

    consul = connect_to_consult(consul_endpoint)
    _, services = consul.catalog.service(service_name)

    for service in services:
        log.debug('service',
                  name=service['ServiceName'],
                  serviceid=service['ServiceID'],
                  serviceport=service['ServicePort'],
                  createindex=service['CreateIndex'])

    return services


def get_endpoint_from_consul(consul_endpoint, service_name):
    """
    Get endpoint of service_name from consul.
    :param consul_endpoint: a <host>:<port> string
    :param service_name: name of service for which endpoint
                         needs to be found.
    :return: service endpoint if available, else exit.
    """
    log.debug('getting-service-info', service=service_name)

    consul = connect_to_consult(consul_endpoint)
    _, services = consul.catalog.service(service_name)

    if len(services) == 0:
        raise Exception(
            'Cannot find service {} in consul'.format(service_name))
        os.exit(1)

    """ Get host IPV4 address
    """
    local_ipv4 = get_my_primary_local_ipv4()
    """ If host IP address from where the request came in matches
        the IP address of the requested service's host IP address,
        pick the endpoint
    """
    for i in range(len(services)):
        service = services[i]
        if service['ServiceAddress'] == local_ipv4:
            log.debug("picking address locally")
            endpoint = '{}:{}'.format(service['ServiceAddress'],
                                      service['ServicePort'])
            return endpoint

    """ If service is not available locally, picak a random
        endpoint for the service from the list
    """
    service = services[randint(0, len(services) - 1)]
    endpoint = '{}:{}'.format(service['ServiceAddress'],
                              service['ServicePort'])

    return endpoint


def get_healthy_instances(consul_endpoint, service_name=None,
                          number_of_expected_services=None):
    """
    Verify in consul if any service is healthy
    :param consul_endpoint: a <host>:<port> string
    :param service_name: name of service to check, optional
    :param number_of_expected_services number of services to check for, optional
    :return: true if healthy, false otherwise
    """

    def check_health(service):
        _, serv_health = consul.health.service(service, passing=True)
        return not serv_health == []

    consul = connect_to_consult(consul_endpoint)

    if service_name is not None:
        return check_health(service_name)

    services = get_all_services(consul_endpoint)

    items = list(services.keys())

    if number_of_expected_services is not None and \
                    len(items) != number_of_expected_services:
        return False

    for item in items:
        if not check_health(item):
            return False

    return True


if __name__ == '__main__':
    # print get_endpoint_from_consul('10.100.198.220:8500', 'kafka')
    # print get_healthy_instances('10.100.198.220:8500', 'voltha-health')
    # print get_healthy_instances('10.100.198.220:8500')
    get_all_instances_of_service('10.100.198.220:8500', 'voltha-grpc')
