// Copyright (c) 2014, the Dart project authors.
// Copyright (c) 2006, Kirill Simonov.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

import 'dart:collection';

import 'package:collection/collection.dart' as pkg_collection;
import 'package:source_span/source_span.dart';

import 'null_span.dart';
import 'style.dart';
import 'yaml_node.dart';

/// A wrapper that makes a normal Dart map behave like a [YamlMap].
class YamlMapWrapper extends MapBase
    with pkg_collection.UnmodifiableMapMixin
    implements YamlMap {
  @override
  final CollectionStyle style;

  final Map _dartMap;

  @override
  final SourceSpan span;

  @override
  final Map<dynamic, YamlNode> nodes;

  @override
  Map get value => this;

  @override
  Iterable get keys => _dartMap.keys;

  YamlMapWrapper(Map dartMap, Object? sourceUrl,
      {CollectionStyle style = CollectionStyle.ANY})
      : this._(dartMap, NullSpan(sourceUrl), style: style);

  YamlMapWrapper._(Map dartMap, this.span, {this.style = CollectionStyle.ANY})
      : _dartMap = dartMap,
        nodes = _YamlMapNodes(dartMap, span) {
    ArgumentError.checkNotNull(style, 'style');
  }

  @override
  dynamic operator [](Object? key) {
    var value = _dartMap[key];
    if (value is Map) return YamlMapWrapper._(value, span);
    if (value is List) return YamlListWrapper._(value, span);
    return value;
  }

  @override
  int get hashCode => _dartMap.hashCode;

  @override
  bool operator ==(Object other) =>
      other is YamlMapWrapper && other._dartMap == _dartMap;
}

/// The implementation of [YamlMapWrapper.nodes] as a wrapper around the Dart
/// map.
class _YamlMapNodes extends MapBase<dynamic, YamlNode>
    with pkg_collection.UnmodifiableMapMixin<dynamic, YamlNode> {
  final Map _dartMap;

  final SourceSpan _span;

  @override
  Iterable get keys =>
      _dartMap.keys.map((key) => YamlScalar.internalWithSpan(key, _span));

  _YamlMapNodes(this._dartMap, this._span);

  @override
  YamlNode? operator [](Object? key) {
    // Use "as" here because key being assigned to invalidates type propagation.
    if (key is YamlScalar) key = key.value;
    if (!_dartMap.containsKey(key)) return null;
    return _nodeForValue(_dartMap[key], _span);
  }

  @override
  int get hashCode => _dartMap.hashCode;

  @override
  bool operator ==(Object other) =>
      other is _YamlMapNodes && other._dartMap == _dartMap;
}

// TODO(nweiz): Use UnmodifiableListMixin when issue 18970 is fixed.
/// A wrapper that makes a normal Dart list behave like a [YamlList].
class YamlListWrapper extends ListBase implements YamlList {
  @override
  final CollectionStyle style;

  final List _dartList;

  @override
  final SourceSpan span;

  @override
  final List<YamlNode> nodes;

  @override
  List get value => this;

  @override
  int get length => _dartList.length;

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

  YamlListWrapper(List dartList, Object? sourceUrl,
      {CollectionStyle style = CollectionStyle.ANY})
      : this._(dartList, NullSpan(sourceUrl), style: style);

  YamlListWrapper._(List dartList, this.span,
      {this.style = CollectionStyle.ANY})
      : _dartList = dartList,
        nodes = _YamlListNodes(dartList, span) {
    ArgumentError.checkNotNull(style, 'style');
  }

  @override
  dynamic operator [](int index) {
    var value = _dartList[index];
    if (value is Map) return YamlMapWrapper._(value, span);
    if (value is List) return YamlListWrapper._(value, span);
    return value;
  }

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

  @override
  int get hashCode => _dartList.hashCode;

  @override
  bool operator ==(Object other) =>
      other is YamlListWrapper && other._dartList == _dartList;
}

// TODO(nweiz): Use UnmodifiableListMixin when issue 18970 is fixed.
/// The implementation of [YamlListWrapper.nodes] as a wrapper around the Dart
/// list.
class _YamlListNodes extends ListBase<YamlNode> {
  final List _dartList;

  final SourceSpan _span;

  @override
  int get length => _dartList.length;

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

  _YamlListNodes(this._dartList, this._span);

  @override
  YamlNode operator [](int index) => _nodeForValue(_dartList[index], _span);

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

  @override
  int get hashCode => _dartList.hashCode;

  @override
  bool operator ==(Object other) =>
      other is _YamlListNodes && other._dartList == _dartList;
}

YamlNode _nodeForValue(Object? value, SourceSpan span) {
  if (value is Map) return YamlMapWrapper._(value, span);
  if (value is List) return YamlListWrapper._(value, span);
  return YamlScalar.internalWithSpan(value, span);
}
