// 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 'package:path/path.dart' as p;
import 'package:collection/collection.dart';

import 'utils.dart';

const _SEPARATOR = 0x2F; // "/"

/// A node in the abstract syntax tree for a glob.
abstract class AstNode {
  /// The cached regular expression that this AST was compiled into.
  RegExp _regExp;

  /// Whether this node matches case-sensitively or not.
  final bool caseSensitive;

  /// Whether this glob could match an absolute path.
  ///
  /// Either this or [canMatchRelative] or both will be true.
  bool get canMatchAbsolute => false;

  /// Whether this glob could match a relative path.
  ///
  /// Either this or [canMatchRelative] or both will be true.
  bool get canMatchRelative => true;

  AstNode._(this.caseSensitive);

  /// Returns a new glob with all the options bubbled to the top level.
  ///
  /// In particular, this returns a glob AST with two guarantees:
  ///
  /// 1. There are no [OptionsNode]s other than the one at the top level.
  /// 2. It matches the same set of paths as [this].
  ///
  /// For example, given the glob `{foo,bar}/{click/clack}`, this would return
  /// `{foo/click,foo/clack,bar/click,bar/clack}`.
  OptionsNode flattenOptions() => new OptionsNode([
        new SequenceNode([this], caseSensitive: caseSensitive)
      ], caseSensitive: caseSensitive);

  /// Returns whether this glob matches [string].
  bool matches(String string) {
    if (_regExp == null) {
      _regExp = new RegExp('^${_toRegExp()}\$', caseSensitive: caseSensitive);
    }
    return _regExp.hasMatch(string);
  }

  /// Subclasses should override this to return a regular expression component.
  String _toRegExp();
}

/// A sequence of adjacent AST nodes.
class SequenceNode extends AstNode {
  /// The nodes in the sequence.
  final List<AstNode> nodes;

  bool get canMatchAbsolute => nodes.first.canMatchAbsolute;
  bool get canMatchRelative => nodes.first.canMatchRelative;

  SequenceNode(Iterable<AstNode> nodes, {bool caseSensitive: true})
      : nodes = nodes.toList(),
        super._(caseSensitive);

  OptionsNode flattenOptions() {
    if (nodes.isEmpty) {
      return new OptionsNode([this], caseSensitive: caseSensitive);
    }

    var sequences =
        nodes.first.flattenOptions().options.map((sequence) => sequence.nodes);
    for (var node in nodes.skip(1)) {
      // Concatenate all sequences in the next options node ([nextSequences])
      // onto all previous sequences ([sequences]).
      var nextSequences = node.flattenOptions().options;
      sequences = sequences.expand((sequence) {
        return nextSequences.map((nextSequence) {
          return sequence.toList()..addAll(nextSequence.nodes);
        });
      });
    }

    return new OptionsNode(sequences.map((sequence) {
      // Combine any adjacent LiteralNodes in [sequence].
      return new SequenceNode(
          sequence.fold<List<AstNode>>([], (combined, node) {
            if (combined.isEmpty ||
                combined.last is! LiteralNode ||
                node is! LiteralNode) {
              return combined..add(node);
            }

            combined[combined.length - 1] = new LiteralNode(
                // TODO(nweiz): Avoid casting when sdk#25565 is fixed.
                (combined.last as LiteralNode).text +
                    (node as LiteralNode).text,
                caseSensitive: caseSensitive);
            return combined;
          }),
          caseSensitive: caseSensitive);
    }), caseSensitive: caseSensitive);
  }

  /// Splits this glob into components along its path separators.
  ///
  /// For example, given the glob `foo/*/*.dart`, this would return three globs:
  /// `foo`, `*`, and `*.dart`.
  ///
  /// Path separators within options nodes are not split. For example,
  /// `foo/{bar,baz/bang}/qux` will return three globs: `foo`, `{bar,baz/bang}`,
  /// and `qux`.
  ///
  /// [context] is used to determine what absolute roots look like for this
  /// glob.
  List<SequenceNode> split(p.Context context) {
    var componentsToReturn = <SequenceNode>[];
    List<AstNode> currentComponent;

    addNode(AstNode node) {
      if (currentComponent == null) currentComponent = [];
      currentComponent.add(node);
    }

    finishComponent() {
      if (currentComponent == null) return;
      componentsToReturn.add(
          new SequenceNode(currentComponent, caseSensitive: caseSensitive));
      currentComponent = null;
    }

    for (var node in nodes) {
      if (node is! LiteralNode) {
        addNode(node);
        continue;
      }

      // TODO(nweiz): Avoid casting when sdk#25565 is fixed.
      var literal = node as LiteralNode;
      if (!literal.text.contains('/')) {
        addNode(literal);
        continue;
      }

      var text = literal.text;
      if (context.style == p.Style.windows) text = text.replaceAll("/", "\\");
      var components = context.split(text);

      // If the first component is absolute, that means it's a separator (on
      // Windows some non-separator things are also absolute, but it's invalid
      // to have "C:" show up in the middle of a path anyway).
      if (context.isAbsolute(components.first)) {
        // If this is the first component, it's the root.
        if (componentsToReturn.isEmpty && currentComponent == null) {
          var root = components.first;
          if (context.style == p.Style.windows) {
            // Above, we switched to backslashes to make [context.split] handle
            // roots properly. That means that if there is a root, it'll still
            // have backslashes, where forward slashes are required for globs.
            // So we switch it back here.
            root = root.replaceAll("\\", "/");
          }
          addNode(new LiteralNode(root, caseSensitive: caseSensitive));
        }
        finishComponent();
        components = components.skip(1);
        if (components.isEmpty) continue;
      }

      // For each component except the last one, add a separate sequence to
      // [sequences] containing only that component.
      for (var component in components.take(components.length - 1)) {
        addNode(new LiteralNode(component, caseSensitive: caseSensitive));
        finishComponent();
      }

      // For the final component, only end its sequence (by adding a new empty
      // sequence) if it ends with a separator.
      addNode(new LiteralNode(components.last, caseSensitive: caseSensitive));
      if (literal.text.endsWith('/')) finishComponent();
    }

    finishComponent();
    return componentsToReturn;
  }

  String _toRegExp() => nodes.map((node) => node._toRegExp()).join();

  bool operator ==(Object other) =>
      other is SequenceNode &&
      const IterableEquality().equals(nodes, other.nodes);

  int get hashCode => const IterableEquality().hash(nodes);

  String toString() => nodes.join();
}

/// A node matching zero or more non-separator characters.
class StarNode extends AstNode {
  StarNode({bool caseSensitive: true}) : super._(caseSensitive);

  String _toRegExp() => '[^/]*';

  bool operator ==(Object other) => other is StarNode;

  int get hashCode => 0;

  String toString() => '*';
}

/// A node matching zero or more characters that may be separators.
class DoubleStarNode extends AstNode {
  /// The path context for the glob.
  ///
  /// This is used to determine what absolute paths look like.
  final p.Context _context;

  DoubleStarNode(this._context, {bool caseSensitive: true})
      : super._(caseSensitive);

  String _toRegExp() {
    // Double star shouldn't match paths with a leading "../", since these paths
    // wouldn't be listed with this glob. We only check for "../" at the
    // beginning since the paths are normalized before being checked against the
    // glob.
    var buffer = new StringBuffer()..write(r'(?!^(?:\.\./|');

    // A double star at the beginning of the glob also shouldn't match absolute
    // paths, since those also wouldn't be listed. Which root patterns we look
    // for depends on the style of path we're matching.
    if (_context.style == p.Style.posix) {
      buffer.write(r'/');
    } else if (_context.style == p.Style.windows) {
      buffer.write(r'//|[A-Za-z]:/');
    } else {
      assert(_context.style == p.Style.url);
      buffer.write(r'[a-zA-Z][-+.a-zA-Z\d]*://|/');
    }

    // Use `[^]` rather than `.` so that it matches newlines as well.
    buffer.write(r'))[^]*');

    return buffer.toString();
  }

  bool operator ==(Object other) => other is DoubleStarNode;

  int get hashCode => 1;

  String toString() => '**';
}

/// A node matching a single non-separator character.
class AnyCharNode extends AstNode {
  AnyCharNode({bool caseSensitive: true}) : super._(caseSensitive);

  String _toRegExp() => '[^/]';

  bool operator ==(Object other) => other is AnyCharNode;

  int get hashCode => 2;

  String toString() => '?';
}

/// A node matching a single character in a range of options.
class RangeNode extends AstNode {
  /// The ranges matched by this node.
  ///
  /// The ends of the ranges are unicode code points.
  final Set<Range> ranges;

  /// Whether this range was negated.
  final bool negated;

  RangeNode(Iterable<Range> ranges, {this.negated, bool caseSensitive: true})
      : ranges = ranges.toSet(),
        super._(caseSensitive);

  OptionsNode flattenOptions() {
    if (negated || ranges.any((range) => !range.isSingleton)) {
      return super.flattenOptions();
    }

    // If a range explicitly lists a set of characters, return each character as
    // a separate expansion.
    return new OptionsNode(ranges.map((range) {
      return new SequenceNode([
        new LiteralNode(new String.fromCharCodes([range.min]),
            caseSensitive: caseSensitive)
      ], caseSensitive: caseSensitive);
    }), caseSensitive: caseSensitive);
  }

  String _toRegExp() {
    var buffer = new StringBuffer();

    var containsSeparator = ranges.any((range) => range.contains(_SEPARATOR));
    if (!negated && containsSeparator) {
      // Add `(?!/)` because ranges are never allowed to match separators.
      buffer.write('(?!/)');
    }

    buffer.write('[');
    if (negated) {
      buffer.write('^');
      // If the range doesn't itself exclude separators, exclude them ourselves,
      // since ranges are never allowed to match them.
      if (!containsSeparator) buffer.write('/');
    }

    for (var range in ranges) {
      var start = new String.fromCharCodes([range.min]);
      buffer.write(regExpQuote(start));
      if (range.isSingleton) continue;
      buffer.write('-');
      buffer.write(regExpQuote(new String.fromCharCodes([range.max])));
    }

    buffer.write(']');
    return buffer.toString();
  }

  bool operator ==(Object other) {
    if (other is! RangeNode) return false;
    if ((other as RangeNode).negated != negated) return false;
    return const SetEquality().equals(ranges, (other as RangeNode).ranges);
  }

  int get hashCode => (negated ? 1 : 3) * const SetEquality().hash(ranges);

  String toString() {
    var buffer = new StringBuffer()..write('[');
    for (var range in ranges) {
      buffer.writeCharCode(range.min);
      if (range.isSingleton) continue;
      buffer.write('-');
      buffer.writeCharCode(range.max);
    }
    buffer.write(']');
    return buffer.toString();
  }
}

/// A node that matches one of several options.
class OptionsNode extends AstNode {
  /// The options to match.
  final List<SequenceNode> options;

  bool get canMatchAbsolute => options.any((node) => node.canMatchAbsolute);
  bool get canMatchRelative => options.any((node) => node.canMatchRelative);

  OptionsNode(Iterable<SequenceNode> options, {bool caseSensitive: true})
      : options = options.toList(),
        super._(caseSensitive);

  OptionsNode flattenOptions() => new OptionsNode(
      options.expand((option) => option.flattenOptions().options),
      caseSensitive: caseSensitive);

  String _toRegExp() =>
      '(?:${options.map((option) => option._toRegExp()).join("|")})';

  bool operator ==(Object other) =>
      other is OptionsNode &&
      const UnorderedIterableEquality().equals(options, other.options);

  int get hashCode => const UnorderedIterableEquality().hash(options);

  String toString() => '{${options.join(',')}}';
}

/// A node that matches a literal string.
class LiteralNode extends AstNode {
  /// The string to match.
  final String text;

  /// The path context for the glob.
  ///
  /// This is used to determine whether this could match an absolute path.
  final p.Context _context;

  bool get canMatchAbsolute {
    var nativeText =
        _context.style == p.Style.windows ? text.replaceAll('/', '\\') : text;
    return _context.isAbsolute(nativeText);
  }

  bool get canMatchRelative => !canMatchAbsolute;

  LiteralNode(this.text, {p.Context context, bool caseSensitive: true})
      : _context = context,
        super._(caseSensitive);

  String _toRegExp() => regExpQuote(text);

  bool operator ==(Object other) => other is LiteralNode && other.text == text;

  int get hashCode => text.hashCode;

  String toString() => text;
}
