// Copyright (c) 2012, 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.

part of yaml;

// This file contains the node classes for the internal representations of YAML
// documents. These nodes are used for both the serialization tree and the
// representation graph.

/// A tag that indicates the type of a YAML node.
class _Tag {
  // TODO(nweiz): it would better match the semantics of the spec if there were
  // a singleton instance of this class for each tag.

  static const SCALAR_KIND = 0;
  static const SEQUENCE_KIND = 1;
  static const MAPPING_KIND = 2;

  static const String YAML_URI_PREFIX = 'tag:yaml.org,2002:';

  /// The name of the tag, either a URI or a local tag beginning with "!".
  final String name;

  /// The kind of the tag: SCALAR_KIND, SEQUENCE_KIND, or MAPPING_KIND.
  final int kind;

  _Tag(this.name, this.kind);

  _Tag.scalar(String name) : this(name, SCALAR_KIND);
  _Tag.sequence(String name) : this(name, SEQUENCE_KIND);
  _Tag.mapping(String name) : this(name, MAPPING_KIND);

  /// Returns the standard YAML tag URI for [type].
  static String yaml(String type) => "tag:yaml.org,2002:$type";

  /// Two tags are equal if their URIs are equal.
  operator ==(other) {
    if (other is! _Tag) return false;
    return name == other.name;
  }

  String toString() {
    if (name.startsWith(YAML_URI_PREFIX)) {
      return '!!${name.substring(YAML_URI_PREFIX.length)}';
    } else {
      return '!<$name>';
    }
  }

  int get hashCode => name.hashCode;
}

/// The abstract class for YAML nodes.
abstract class _Node {
  /// Every YAML node has a tag that describes its type.
  _Tag tag;

  /// Any YAML node can have an anchor associated with it.
  String anchor;

  _Node(this.tag, [this.anchor]);

  bool operator ==(other) {
    if (other is! _Node) return false;
    return tag == other.tag;
  }

  int get hashCode => _hashCode([tag, anchor]);

  visit(_Visitor v);
}

/// A sequence node represents an ordered list of nodes.
class _SequenceNode extends _Node {
  /// The nodes in the sequence.
  List<_Node> content;

  _SequenceNode(String tagName, this.content)
    : super(new _Tag.sequence(tagName));

  /// Two sequences are equal if their tags and contents are equal.
  bool operator ==(other) {
    // Should be super != other; bug 2554
    if (!(super == other) || other is! _SequenceNode) return false;
    if (content.length != other.content.length) return false;
    for (var i = 0; i < content.length; i++) {
      if (content[i] != other.content[i]) return false;
    }
    return true;
  }

  String toString() =>
      '$tag [${Strings.join(content.mappedBy((e) => '$e'), ', ')}]';

  int get hashCode => super.hashCode ^ _hashCode(content);

  visit(_Visitor v) => v.visitSequence(this);
}

/// An alias node is a reference to an anchor.
class _AliasNode extends _Node {
  _AliasNode(String anchor) : super(new _Tag.scalar(_Tag.yaml("str")), anchor);

  visit(_Visitor v) => v.visitAlias(this);
}

/// A scalar node represents all YAML nodes that have a single value.
class _ScalarNode extends _Node {
  /// The string value of the scalar node, if it was created by the parser.
  final String _content;

  /// The Dart value of the scalar node, if it was created by the composer.
  final value;

  /// Creates a new Scalar node.
  ///
  /// Exactly one of [content] and [value] should be specified. Content should
  /// be specified for a newly-parsed scalar that hasn't yet been composed.
  /// Value should be specified for a composed scalar, although `null` is a
  /// valid value.
  _ScalarNode(String tagName, {String content, this.value})
   : _content = content,
     super(new _Tag.scalar(tagName));

  /// Two scalars are equal if their string representations are equal.
  bool operator ==(other) {
    // Should be super != other; bug 2554
    if (!(super == other) || other is! _ScalarNode) return false;
    return content == other.content;
  }

  /// Returns the string representation of the scalar. After composition, this
  /// is equal to the canonical serialization of the value of the scalar.
  String get content => _content != null ? _content : canonicalContent;

  /// Returns the canonical serialization of the value of the scalar. If the
  /// value isn't given, the result of this will be "null".
  String get canonicalContent {
    if (value == null || value is bool || value is int) return '$value';

    if (value is num) {
      // 20 is the maximum value for this argument, which we use since YAML
      // doesn't specify a maximum.
      return value.toStringAsExponential(20).
        replaceFirst(new RegExp("0+e"), "e");
    }

    if (value is String) {
      // TODO(nweiz): This could be faster if we used a RegExp to check for
      // special characters and short-circuited if they didn't exist.

      var escapedValue = value.charCodes.mappedBy((c) {
        switch (c) {
        case _Parser.TAB: return "\\t";
        case _Parser.LF: return "\\n";
        case _Parser.CR: return "\\r";
        case _Parser.DOUBLE_QUOTE: return '\\"';
        case _Parser.NULL: return "\\0";
        case _Parser.BELL: return "\\a";
        case _Parser.BACKSPACE: return "\\b";
        case _Parser.VERTICAL_TAB: return "\\v";
        case _Parser.FORM_FEED: return "\\f";
        case _Parser.ESCAPE: return "\\e";
        case _Parser.BACKSLASH: return "\\\\";
        case _Parser.NEL: return "\\N";
        case _Parser.NBSP: return "\\_";
        case _Parser.LINE_SEPARATOR: return "\\L";
        case _Parser.PARAGRAPH_SEPARATOR: return "\\P";
        default:
          if (c < 0x20 || (c >= 0x7f && c < 0x100)) {
            return "\\x${zeroPad(c.toRadixString(16).toUpperCase(), 2)}";
          } else if (c >= 0x100 && c < 0x10000) {
            return "\\u${zeroPad(c.toRadixString(16).toUpperCase(), 4)}";
          } else if (c >= 0x10000) {
            return "\\u${zeroPad(c.toRadixString(16).toUpperCase(), 8)}";
          } else {
            return new String.fromCharCodes([c]);
          }
        }
      });
      return '"${Strings.join(escapedValue, '')}"';
    }

    throw new YamlException("unknown scalar value: $value");
  }

  String toString() => '$tag "$content"';

  /// Left-pads [str] with zeros so that it's at least [length] characters
  /// long.
  String zeroPad(String str, int length) {
    assert(length >= str.length);
    var prefix = [];
    prefix.insertRange(0, length - str.length, '0');
    return '${Strings.join(prefix, '')}$str';
  }

  int get hashCode => super.hashCode ^ content.hashCode;

  visit(_Visitor v) => v.visitScalar(this);
}

/// A mapping node represents an unordered map of nodes to nodes.
class _MappingNode extends _Node {
  /// The node map.
  Map<_Node, _Node> content;

  _MappingNode(String tagName, this.content)
    : super(new _Tag.mapping(tagName));

  /// Two mappings are equal if their tags and contents are equal.
  bool operator ==(other) {
    // Should be super != other; bug 2554
    if (!(super == other) || other is! _MappingNode) return false;
    if (content.length != other.content.length) return false;
    for (var key in content.keys) {
      if (!other.content.containsKey(key)) return false;
      if (content[key] != other.content[key]) return false;
    }
    return true;
  }

  String toString() {
    var strContent = content.keys
        .mappedBy((k) => '${k}: ${content[k]}')
        .join(', ');
    return '$tag {$strContent}';
  }

  int get hashCode => super.hashCode ^ _hashCode(content);

  visit(_Visitor v) => v.visitMapping(this);
}
