#
# 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 platform
import re
from itertools import product

from .util import merge_dict

# Those keys are passed to execution as is.
# Note that there are keys other than these, namely:
# delay: After server is started, client start is delayed for the value
# (seconds).
# timeout: Test timeout after client is started (seconds).
# platforms: Supported platforms. Should match platform.system() value.
# protocols: list of supported protocols
# transports: list of supported transports
# sockets: list of supported sockets
#
# protocols and transports entries can be colon separated "spec:impl" pair
# (e.g. binary:accel) where test is run for any matching "spec" while actual
# argument passed to test executable is "impl".
# Otherwise "spec" is equivalent to "spec:spec" pair.
# (e.g. "binary" is equivalent to "binary:binary" in tests.json)
#
VALID_JSON_KEYS = [
  'name',  # name of the library, typically a language name
  'workdir',  # work directory where command is executed
  'command',  # test command
  'extra_args',  # args appended to command after other args are appended
  'join_args',  # whether args should be passed as single concatenated string
  'env',  # additional environmental variable
]

DEFAULT_DELAY = 1
DEFAULT_TIMEOUT = 5


def _collect_testlibs(config, server_match, client_match=[None]):
  """Collects server/client configurations from library configurations"""
  def expand_libs(config):
    for lib in config:
      sv = lib.pop('server', None)
      cl = lib.pop('client', None)
      yield lib, sv, cl

  def yield_testlibs(base_configs, configs, match):
    for base, conf in zip(base_configs, configs):
      if conf:
        if not match or base['name'] in match:
          platforms = conf.get('platforms') or base.get('platforms')
          if not platforms or platform.system() in platforms:
            yield merge_dict(base, conf)

  libs, svs, cls = zip(*expand_libs(config))
  servers = list(yield_testlibs(libs, svs, server_match))
  clients = list(yield_testlibs(libs, cls, client_match))
  return servers, clients


def collect_features(config, match):
  res = list(map(re.compile, match))
  return list(filter(lambda c: any(map(lambda r: r.search(c['name']), res)), config))


def _do_collect_tests(servers, clients):
  def intersection(key, o1, o2):
    """intersection of two collections.
    collections are replaced with sets the first time"""
    def cached_set(o, key):
      v = o[key]
      if not isinstance(v, set):
        v = set(v)
        o[key] = v
      return v
    return cached_set(o1, key) & cached_set(o2, key)

  def intersect_with_spec(key, o1, o2):
    # store as set of (spec, impl) tuple
    def cached_set(o):
      def to_spec_impl_tuples(values):
        for v in values:
          spec, _, impl = v.partition(':')
          yield spec, impl or spec
      v = o[key]
      if not isinstance(v, set):
        v = set(to_spec_impl_tuples(set(v)))
        o[key] = v
      return v
    for spec1, impl1 in cached_set(o1):
      for spec2, impl2 in cached_set(o2):
        if spec1 == spec2:
          name = impl1 if impl1 == impl2 else '%s-%s' % (impl1, impl2)
          yield name, impl1, impl2

  def maybe_max(key, o1, o2, default):
    """maximum of two if present, otherwise defult value"""
    v1 = o1.get(key)
    v2 = o2.get(key)
    return max(v1, v2) if v1 and v2 else v1 or v2 or default

  def filter_with_validkeys(o):
    ret = {}
    for key in VALID_JSON_KEYS:
      if key in o:
        ret[key] = o[key]
    return ret

  def merge_metadata(o, **ret):
    for key in VALID_JSON_KEYS:
      if key in o:
        ret[key] = o[key]
    return ret

  for sv, cl in product(servers, clients):
    for proto, proto1, proto2 in intersect_with_spec('protocols', sv, cl):
      for trans, trans1, trans2 in intersect_with_spec('transports', sv, cl):
        for sock in intersection('sockets', sv, cl):
          yield {
            'server': merge_metadata(sv, **{'protocol': proto1, 'transport': trans1}),
            'client': merge_metadata(cl, **{'protocol': proto2, 'transport': trans2}),
            'delay': maybe_max('delay', sv, cl, DEFAULT_DELAY),
            'timeout': maybe_max('timeout', sv, cl, DEFAULT_TIMEOUT),
            'protocol': proto,
            'transport': trans,
            'socket': sock
          }


def collect_cross_tests(tests_dict, server_match, client_match):
  sv, cl = _collect_testlibs(tests_dict, server_match, client_match)
  return list(_do_collect_tests(sv, cl))


def collect_feature_tests(tests_dict, features_dict, server_match, feature_match):
  sv, _ = _collect_testlibs(tests_dict, server_match)
  ft = collect_features(features_dict, feature_match)
  return list(_do_collect_tests(sv, ft))
