'''
'''
#  Licensed to the Apache Software Foundation (ASF) under one
#  or more contributor license agreements.  See the NOTICE file
#  distributed with this work for additional information
#  regarding copyright ownership.  The ASF licenses this file
#  to you 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.

import subprocess
import json
import re


def HasOpenSSLVersion(self, version):
    output = subprocess.check_output(
        os.path.join(self.Variables.BINDIR, "traffic_layout") + " info --versions --json", shell=True
    )
    json_data = output.decode('utf-8')
    openssl_str = json.loads(json_data)['openssl_str']
    exe_ver = re.search(r'\d\.\d\.\d', openssl_str).group(0)
    if exe_ver == '':
        raise ValueError("Error determining version of OpenSSL library needed by traffic_server executable")
    return self.Condition(
        lambda: exe_ver >= version,
        "OpenSSL library version is " + exe_ver + ", must be at least " + version
    )


def IsBoringSSL(self):
    output = subprocess.check_output(
        os.path.join(self.Variables.BINDIR, "traffic_layout") + " info --versions --json", shell=True
    )
    json_data = output.decode('utf-8')
    openssl_str = json.loads(json_data)['openssl_str']
    return self.Condition(
        # OpenSSL 1.1.1 (compatible; BoringSSL)
        lambda: "compatible; BoringSSL" in openssl_str,
        "SSL library is not BoringSSL"
    )


def IsOpenSSL(self):
    output = subprocess.check_output(
        os.path.join(self.Variables.BINDIR, "traffic_layout") + " info --versions --json", shell=True
    )
    json_data = output.decode('utf-8')
    openssl_str = json.loads(json_data)['openssl_str']
    return self.Condition(
        # OpenSSL 1.1.1k  25 Mar 2021
        lambda: "OpenSSL" in openssl_str and "compatible; BoringSSL" not in openssl_str,
        "SSL library is not OpenSSL"
    )


def HasCurlVersion(self, version):
    return self.EnsureVersion(["curl", "--version"], min_version=version)


def HasProxyVerifierVersion(self, version):
    return self.EnsureVersion(["verifier-client", "--version"], min_version=version)


def HasCurlFeature(self, feature):

    def default(output):
        FEATURE_TAG = 'Features:'
        tag = feature.lower()
        for line in output.splitlines():
            # look for line with starting with the Features
            if line.startswith(FEATURE_TAG):
                # get a features and lower case then for safety
                line = line[len(FEATURE_TAG):].lower()
                tokens = line.split()
                for t in tokens:
                    if t == tag:
                        return True
        return False

    return self.CheckOutput(
        ['curl', '--version'],
        default,
        "Curl needs to support feature: {feature}".format(feature=feature)
    )


def HasCurlOption(self, option):
    def default(output):
        tag = option.lower()
        for line in output.splitlines():
            line = line.lower()
            tokens = line.split()
            for t in tokens:
                if t == tag:
                    return True
        return False

    return self.CheckOutput(
        ['curl', '--help', 'all'],
        default,
        "Curl needs to support option: {option}".format(option=option)
    )


def HasATSFeature(self, feature):

    val = self.Variables.get(feature, None)

    return self.Condition(
        lambda: val,
        "ATS feature not enabled: {feature}".format(feature=feature)
    )

# test if a plugin exists in the libexec folder


def PluginExists(self, pluginname):

    path = os.path.join(self.Variables.PLUGINDIR, pluginname)
    return self.Condition(lambda: os.path.isfile(path), path + " not found.")


ExtendCondition(HasOpenSSLVersion)
ExtendCondition(IsBoringSSL)
ExtendCondition(IsOpenSSL)
ExtendCondition(HasATSFeature)
ExtendCondition(HasCurlVersion)
ExtendCondition(HasCurlFeature)
ExtendCondition(HasCurlOption)
ExtendCondition(PluginExists)
