# Copyright (c) 2018-2020 VMware, Inc.  All rights reserved.
# -- VMware Confidential

'''
This file contains the provider class which initializes
client for WCP Data Provider running on the given vcHost
'''
import os
import sys
import logging
import requests

logger = logging.getLogger(__name__)
rootDir = os.path.abspath(os.path.dirname(__file__))
sys.path.append(os.path.join(rootDir, '../../../', 'libs'))
sys.path.extend(os.environ['VMWARE_VAPI_PYTHONPATH'].split(':'))

from vmware.vapi.lib.connect import get_requests_connector
from vmware.vapi.stdlib.client.factories import StubConfigurationFactory

sys.path.append(os.path.join(rootDir, '../../../', 'libs',
                             'resource-model-bindings'))
from com.vmware.cis.data import provider_client
from com.vmware.cis.data.provider import metadata_client

from . import authentication

_PropertyPredicate = provider_client.ResourceModel.PropertyPredicate
_Filter = provider_client.ResourceModel.Filter
_ComparisonOperator = _PropertyPredicate.ComparisonOperator
_SortCriterion = provider_client.ResourceModel.SortCriterion
_SortDirection = provider_client.ResourceModel.SortCriterion.SortDirection


class DataProvider:
    def __init__(self, vcHost, verifyServerSSLCert=False,
                 authenticate=True, vcHttpsPort=None):
        """
        Initializes client for WCP Data Provider running on given vcHost.
        By default it will not verify TLS certificate and will authenticate
        requests.
        Authentication may be disabled by setting authenticate to False.
        """

        logger.info("initializing WCP Precheck Data Provider")
        self.vcHost = vcHost
        self.vcHttpsPort = _getVcPort()
        self.verifyServerSSLCert = verifyServerSSLCert
        session = requests.session()
        session.verify = verifyServerSSLCert
        connector = get_requests_connector(session=session,
                                           url=('https://%s:%s/wcp' % (
                                           self.vcHost, self.vcHttpsPort)))
        if authenticate:
            logger.info("WCP Pre-check Data provider Starting Authentication")
            authenticator = authentication.WCPAuthenticator(self.vcHost,
                                                            self.vcHttpsPort)
            sec_ctx = authenticator.get_session_security_context()
            connector.set_security_context(sec_ctx)
            logger.info("WCP Pre-check Data provider Authentication Successful")
        self._stub_cfg = StubConfigurationFactory.new_std_configuration(
            connector)

    @staticmethod
    def create_predicate(operator, property, value):
        """
        Returns a resource model property predicate. Matches all instances of
        resource models listed in :attr:`ResourceModel.QuerySpec.resource_models`
        that have a property which satisifes this condition.
        """
        predict = provider_client.ResourceModel.PropertyPredicate()
        predict.property = property
        predict.operator = operator
        if operator == provider_client.ResourceModel.PropertyPredicate.\
                ComparisonOperator.IN:
            predict.comparable_list = value
        else:
            predict.comparable_value = value
        return predict

    @staticmethod
    def create_filter(operator, criteria):
        """
        Returns the filter criteria that each resource model should
        satisfy in order to qualify for the final result set for
        a given query.
        """
        filter = provider_client.ResourceModel.Filter()
        filter.operator = operator
        filter.criteria = criteria
        return filter

    @staticmethod
    def create_query_spec(resource_models, property, filter):
        """
        Creates and returns a query which encapsulates a request for
        specific resource model data. The query is created taking into
        account the specific filtering criterias and retrieval
        of arbitrary number of properties or sub-properties of the
        resource models that satisfy the filter criteria.
        """
        query_spec = provider_client.ResourceModel.QuerySpec()
        query_spec.resource_models = resource_models
        query_spec.properties = property
        query_spec.filter = filter
        return query_spec

    def get_metadata_schema(self):
        """
        Returns Information about the resource model schema of the Data Provider
        The schema describes all resource models supported by the provider as
        well as information about the model properties and how they could be
        queried
        """
        schema_obj = metadata_client.Schema(self._stub_cfg)
        return schema_obj.get()

    def query_data(self, query_spec):
        """
        Executes the provided query spec and
        retrieve a snapshot of the resource model data as
        specified in the query.
        """
        rs_obj = provider_client.ResourceModel(self._stub_cfg)
        return rs_obj.query(query_spec)


def _getVcPort():
    ''' VC can have custom port for the rhttp port and this function tries to
    find the correct one
    '''
    try:
        from cis.tools import get_install_parameter
    except ImportError:
        logger.info(
            "Cannot import get_install_parameter, will return default value")
        return 443
    vcPort = int(get_install_parameter("rhttpproxy.ext.port2", "443", True))
    logger.info("Port found: %s", vcPort)
    return vcPort
