#
# 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
  'remote_args',  # args added to the other side of the program
  '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))
