// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:collection';

import 'package:yaml/src/event.dart';
import 'package:yaml/yaml.dart';

/// Given a [map], return the [YamlNode] associated with the given [key], or
/// `null` if there is no matching key.
YamlNode getKey(YamlMap map, String key) {
  for (YamlNode k in map.nodes.keys) {
    if (k is YamlScalar && k.value == key) {
      return k;
    }
  }
  return null;
}

/// Given a [map], return the value associated with the key whose value matches
/// the given [key], or `null` if there is no matching key.
YamlNode getValue(YamlMap map, String key) {
  for (var k in map.nodes.keys) {
    if (k is YamlScalar && k.value == key) {
      return map.nodes[k];
    }
  }
  return null;
}

/// If all of the elements of [list] are strings, return a list of strings
/// containing the same elements. Otherwise, return `null`.
List<String> toStringList(List list) {
  if (list == null) {
    return null;
  }
  List<String> stringList = <String>[];
  for (var element in list) {
    if (element is String) {
      stringList.add(element);
    } else {
      return null;
    }
  }
  return stringList;
}

bool _contains(YamlList l1, YamlNode n2) {
  for (YamlNode n1 in l1.nodes) {
    if (n1.value == n2.value) {
      return true;
    }
  }
  return false;
}

/// Merges two maps (of yaml) with simple override semantics, suitable for
/// merging two maps where one map defines default values that are added to
/// (and possibly overridden) by an overriding map.
class Merger {
  /// Merges a default [o1] with an overriding object [o2].
  ///
  ///   * lists are merged (without duplicates).
  ///   * lists of scalar values can be promoted to simple maps when merged with
  ///     maps of strings to booleans (e.g., ['opt1', 'opt2'] becomes
  ///     {'opt1': true, 'opt2': true}.
  ///   * maps are merged recursively.
  ///   * if map values cannot be merged, the overriding value is taken.
  ///
  YamlNode merge(YamlNode o1, YamlNode o2) {
    // Handle promotion first.
    YamlMap listToMap(YamlList list) {
      Map<YamlNode, YamlNode> map = new HashMap<YamlNode,
          YamlNode>(); // equals: _equals, hashCode: _hashCode
      ScalarEvent event = new ScalarEvent(null, 'true', ScalarStyle.PLAIN);
      for (var element in list.nodes) {
        map[element] = new YamlScalar.internal(true, event);
      }
      return new YamlMap.internal(map, null, CollectionStyle.BLOCK);
    }

    if (isListOfString(o1) && isMapToBools(o2)) {
      o1 = listToMap(o1 as YamlList);
    } else if (isMapToBools(o1) && isListOfString(o2)) {
      o2 = listToMap(o2 as YamlList);
    }

    if (o1 is YamlMap && o2 is YamlMap) {
      return mergeMap(o1, o2);
    }
    if (o1 is YamlList && o2 is YamlList) {
      return mergeList(o1, o2);
    }
    // Default to override, unless the overriding value is `null`.
    return o2 ?? o1;
  }

  /// Merge lists, avoiding duplicates.
  YamlList mergeList(YamlList l1, YamlList l2) {
    List<YamlNode> list = <YamlNode>[];
    list.addAll(l1.nodes);
    for (YamlNode n2 in l2.nodes) {
      if (!_contains(l1, n2)) {
        list.add(n2);
      }
    }
    return new YamlList.internal(list, null, CollectionStyle.BLOCK);
  }

  /// Merge maps (recursively).
  YamlMap mergeMap(YamlMap m1, YamlMap m2) {
    Map<YamlNode, YamlNode> merged = new HashMap<YamlNode,
        YamlNode>(); // equals: _equals, hashCode: _hashCode
    m1.nodes.forEach((k, v) {
      merged[k] = v;
    });
    m2.nodes.forEach((k, v) {
      YamlScalar mergedKey = merged.keys
          .firstWhere((key) => key.value == k.value, orElse: () => k);
      merged[mergedKey] = merge(merged[mergedKey], v);
    });
    return new YamlMap.internal(merged, null, CollectionStyle.BLOCK);
  }

  static bool isListOfString(Object o) =>
      o is YamlList &&
      o.nodes.every((e) => e is YamlScalar && e.value is String);

  static bool isMapToBools(Object o) =>
      o is YamlMap &&
      o.nodes.values.every((v) => v is YamlScalar && v.value is bool);
}
