# -*- coding: utf-8 -*-
'''
A route is a rule that specifies how certain packets should be handled by the
virtual network. Routes are associated with virtual machine instances by tag,
and the set of routes for a particular VM is called its routing table.
For each packet leaving a virtual machine, the system searches that machine's
routing table for a single best matching route.

.. versionadded:: 2018.3.0

This module will create a route to send traffic destined to the Internet
through your gateway instance.

:codeauthor: :email:`Pratik Bandarkar <pratik.bandarkar@gmail.com>`
:maturity:   new
:depends:    google-api-python-client
:platform:   Linux

'''

# Import Python libs
from __future__ import absolute_import, unicode_literals, print_function
import logging

# Import salt libs
from salt.ext import six

log = logging.getLogger(__name__)

try:
    import googleapiclient.discovery
    import oauth2client.service_account
    HAS_LIB = True
except ImportError:
    HAS_LIB = False

__virtualname__ = 'gcp'


def __virtual__():
    '''
    Check for googleapiclient api
    '''
    if HAS_LIB is False:
        return False, 'Required dependencies \'googleapiclient\' and/or \'oauth2client\' were not found.'
    return __virtualname__


def _get_network(project_id, network_name, service):
    '''
    Fetch network selfLink from network name.
    '''
    return service.networks().get(project=project_id,
                                  network=network_name).execute()


def _get_instance(project_id, instance_zone, name, service):
    '''
    Get instance details
    '''
    return service.instances().get(project=project_id,
                                   zone=instance_zone,
                                   instance=name).execute()


def route_create(credential_file=None,
                 project_id=None,
                 name=None,
                 dest_range=None,
                 next_hop_instance=None,
                 instance_zone=None,
                 tags=None,
                 network=None,
                 priority=None
                 ):
    '''
    Create a route to send traffic destined to the Internet through your
    gateway instance

    credential_file : string
        File location of application default credential. For more information,
        refer: https://developers.google.com/identity/protocols/application-default-credentials
    project_id : string
        Project ID where instance and network resides.
    name : string
        name of the route to create
    next_hop_instance : string
        the name of an instance that should handle traffic matching this route.
    instance_zone : string
        zone where instance("next_hop_instance") resides
    network : string
        Specifies the network to which the route will be applied.
    dest_range : string
        The destination range of outgoing packets that the route will apply to.
    tags : list
        (optional) Identifies the set of instances that this route will apply to.
    priority : int
        (optional) Specifies the priority of this route relative to other routes.
        default=1000

    CLI Example:

    salt 'salt-master.novalocal' gcp.route_create
        credential_file=/root/secret_key.json
        project_id=cp100-170315
        name=derby-db-route1
        next_hop_instance=instance-1
        instance_zone=us-central1-a
        network=default
        dest_range=0.0.0.0/0
        tags=['no-ip']
        priority=700

    In above example, the instances which are having tag "no-ip" will route the
    packet to instance "instance-1"(if packet is intended to other network)
    '''

    credentials = oauth2client.service_account.ServiceAccountCredentials.\
        from_json_keyfile_name(credential_file)
    service = googleapiclient.discovery.build('compute', 'v1',
                                              credentials=credentials)
    routes = service.routes()

    routes_config = {
        'name': six.text_type(name),
        'network': _get_network(project_id, six.text_type(network),
                                service=service)['selfLink'],
        'destRange': six.text_type(dest_range),
        'nextHopInstance': _get_instance(project_id, instance_zone,
                                         next_hop_instance,
                                         service=service)['selfLink'],
        'tags': tags,
        'priority': priority
    }
    route_create_request = routes.insert(project=project_id,
                                         body=routes_config)
    return route_create_request.execute()
