// Copyright (c) 2014, 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: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 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, sourceUrl,
      {CollectionStyle style = CollectionStyle.ANY})
      : this._(dartMap, NullSpan(sourceUrl), style: style);

  YamlMapWrapper._(Map dartMap, SourceSpan span,
      {this.style = CollectionStyle.ANY})
      : _dartMap = dartMap,
        span = span,
        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 as YamlScalar).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 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, sourceUrl,
      {CollectionStyle style = CollectionStyle.ANY})
      : this._(dartList, NullSpan(sourceUrl), style: style);

  YamlListWrapper._(List dartList, SourceSpan span,
      {this.style = CollectionStyle.ANY})
      : _dartList = dartList,
        span = span,
        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
  operator []=(int index, 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
  operator []=(int index, 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(value, SourceSpan span) {
  if (value is Map) return YamlMapWrapper._(value, span);
  if (value is List) return YamlListWrapper._(value, span);
  return YamlScalar.internalWithSpan(value, span);
}
