// Copyright 2020 Google LLC
//
// Licensed 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
//
//     https://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 'dart:collection' as collection;

import 'package:collection/collection.dart';
import 'package:source_span/source_span.dart';
import 'package:yaml/yaml.dart';

import 'equality.dart';
import 'utils.dart';

/// Returns a new [YamlMap] constructed by applying [update] onto the [nodes]
/// of this [YamlMap].
YamlMap updatedYamlMap(YamlMap map, Function(Map) update) {
  final dummyMap = deepEqualsMap();
  dummyMap.addAll(map.nodes);

  update(dummyMap);

  return wrapAsYamlNode(dummyMap) as YamlMap;
}

/// Wraps [value] into a [YamlNode].
///
/// [Map]s, [List]s and Scalars will be wrapped as [YamlMap]s, [YamlList]s,
/// and [YamlScalar]s respectively. If [collectionStyle]/[scalarStyle] is
/// defined, and [value] is a collection or scalar, the wrapped [YamlNode] will
/// have the respective style, otherwise it defaults to the ANY style.
///
/// If a [YamlNode] is passed in, no further wrapping will be done, and the
/// [collectionStyle]/[scalarStyle] will not be applied.
YamlNode wrapAsYamlNode(Object? value,
    {CollectionStyle collectionStyle = CollectionStyle.ANY,
    ScalarStyle scalarStyle = ScalarStyle.ANY}) {
  if (value is YamlScalar) {
    assertValidScalar(value.value);
    return value;
  } else if (value is YamlList) {
    for (final item in value.nodes) {
      wrapAsYamlNode(item);
    }

    return value;
  } else if (value is YamlMap) {
    /// Both [entry.key] and [entry.values] are guaranteed to be [YamlNode]s,
    /// so running this will just assert that they are valid scalars.
    for (final entry in value.nodes.entries) {
      wrapAsYamlNode(entry.key);
      wrapAsYamlNode(entry.value);
    }

    return value;
  } else if (value is Map) {
    return YamlMapWrap(value, collectionStyle: collectionStyle);
  } else if (value is List) {
    return YamlListWrap(value, collectionStyle: collectionStyle);
  } else {
    assertValidScalar(value);

    return YamlScalarWrap(value, style: scalarStyle);
  }
}

/// Internal class that allows us to define a constructor on [YamlScalar]
/// which takes in [style] as an argument.
class YamlScalarWrap implements YamlScalar {
  /// The [ScalarStyle] to be used for the scalar.
  @override
  final ScalarStyle style;

  @override
  final SourceSpan span;

  @override
  final dynamic value;

  YamlScalarWrap(this.value, {this.style = ScalarStyle.ANY, Object? sourceUrl})
      : span = shellSpan(sourceUrl);

  @override
  String toString() => value.toString();
}

/// Internal class that allows us to define a constructor on [YamlMap]
/// which takes in [style] as an argument.
class YamlMapWrap
    with collection.MapMixin, UnmodifiableMapMixin
    implements YamlMap {
  /// The [CollectionStyle] to be used for the map.
  @override
  final CollectionStyle style;

  @override
  final Map<dynamic, YamlNode> nodes;

  @override
  final SourceSpan span;

  factory YamlMapWrap(Map dartMap,
      {CollectionStyle collectionStyle = CollectionStyle.ANY,
      Object? sourceUrl}) {
    final wrappedMap = deepEqualsMap<dynamic, YamlNode>();

    for (final entry in dartMap.entries) {
      final wrappedKey = wrapAsYamlNode(entry.key);
      final wrappedValue = wrapAsYamlNode(entry.value);
      wrappedMap[wrappedKey] = wrappedValue;
    }

    return YamlMapWrap._(wrappedMap,
        style: collectionStyle, sourceUrl: sourceUrl);
  }

  YamlMapWrap._(this.nodes,
      {CollectionStyle style = CollectionStyle.ANY, Object? sourceUrl})
      : span = shellSpan(sourceUrl),
        style = nodes.isEmpty ? CollectionStyle.FLOW : style;

  @override
  dynamic operator [](Object? key) => nodes[key]?.value;

  @override
  Iterable get keys => nodes.keys.map((node) => node.value);

  @override
  Map get value => this;
}

/// Internal class that allows us to define a constructor on [YamlList]
/// which takes in [style] as an argument.
class YamlListWrap with collection.ListMixin implements YamlList {
  /// The [CollectionStyle] to be used for the list.
  @override
  final CollectionStyle style;

  @override
  final List<YamlNode> nodes;

  @override
  final SourceSpan span;

  @override
  int get length => nodes.length;

  @override
  set length(int index) {
    throw UnsupportedError('Cannot modify an unmodifiable List');
  }

  factory YamlListWrap(List dartList,
      {CollectionStyle collectionStyle = CollectionStyle.ANY,
      Object? sourceUrl}) {
    final wrappedList = dartList.map(wrapAsYamlNode).toList();
    return YamlListWrap._(wrappedList,
        style: collectionStyle, sourceUrl: sourceUrl);
  }

  YamlListWrap._(this.nodes,
      {CollectionStyle style = CollectionStyle.ANY, Object? sourceUrl})
      : span = shellSpan(sourceUrl),
        style = nodes.isEmpty ? CollectionStyle.FLOW : style;

  @override
  dynamic operator [](int index) => nodes[index].value;

  @override
  operator []=(int index, value) {
    throw UnsupportedError('Cannot modify an unmodifiable List');
  }

  @override
  List get value => this;
}
