// Copyright (c) 2017, 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:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math' as math;

import 'package:collection/collection.dart';
import 'package:path/path.dart' as p;
import 'package:term_glyph/term_glyph.dart' as glyph;
import 'package:test/test.dart';

import 'descriptor.dart';
import 'sandbox.dart';
import 'utils.dart';

/// A descriptor describing a single file.
///
/// In addition to the normal descriptor methods, this has [read] and
/// [readAsBytes] methods that allows its contents to be read.
///
/// This may be extended outside this package.
abstract class FileDescriptor extends Descriptor {
  /// Creates a new [FileDescriptor] with [name] and [contents].
  ///
  /// The [contents] may be a `String`, a `List<int>`, or a [Matcher]. If it's a
  /// string, [create] creates a UTF-8 file and [validate] parses the physical
  /// file as UTF-8. If it's a [Matcher], [validate] matches it against the
  /// physical file's contents parsed as UTF-8, and [create], [read], and
  /// [readAsBytes] are unsupported.
  ///
  /// If [contents] isn't passed, [create] creates an empty file and [validate]
  /// verifies that the file is empty.
  ///
  /// To match a [Matcher] against a file's binary contents, use [new
  /// FileDescriptor.binaryMatcher] instead.
  factory FileDescriptor(String name, contents) {
    if (contents is String) return new _StringFileDescriptor(name, contents);
    if (contents is List) {
      return new _BinaryFileDescriptor(name, DelegatingList.typed(contents));
    }
    if (contents == null) return new _BinaryFileDescriptor(name, []);
    return new _MatcherFileDescriptor(name, contents);
  }

  /// Creates a new binary [FileDescriptor] with [name] that matches its binary
  /// contents against [matcher].
  ///
  /// The [create], [read], and [readAsBytes] methods are unsupported for this
  /// descriptor.
  factory FileDescriptor.binaryMatcher(String name, Matcher matcher) =>
      new _MatcherFileDescriptor(name, matcher, isBinary: true);

  /// A protected constructor that's only intended for subclasses.
  FileDescriptor.protected(String name) : super(name);

  Future create([String parent]) async {
    // Create the stream before we call [File.openWrite] because it may fail
    // fast (e.g. if this is a matcher file).
    var file = new File(p.join(parent ?? sandbox, name)).openWrite();
    try {
      await readAsBytes().listen(file.add).asFuture();
    } finally {
      await file.close();
    }
  }

  Future validate([String parent]) async {
    var fullPath = p.join(parent ?? sandbox, name);
    var pretty = prettyPath(fullPath);
    if (!(await new File(fullPath).exists())) {
      fail('File not found: "$pretty".');
    }

    await _validate(pretty, await new File(fullPath).readAsBytes());
  }

  /// Validates that [binaryContents] matches the expected contents of
  /// the descriptor.
  ///
  /// The [prettyPath] is a human-friendly representation of the path to the
  /// descriptor.
  void _validate(String prettyPath, List<int> binaryContents);

  /// Reads and decodes the contents of this descriptor as a UTF-8 string.
  ///
  /// This isn't supported for matcher descriptors.
  Future<String> read() => UTF8.decodeStream(readAsBytes());

  /// Reads the contents of this descriptor as a byte stream.
  ///
  /// This isn't supported for matcher descriptors.
  Stream<List<int>> readAsBytes();

  String describe() => name;
}

class _BinaryFileDescriptor extends FileDescriptor {
  /// The contents of this descriptor's file.
  final List<int> _contents;

  _BinaryFileDescriptor(String name, this._contents) : super.protected(name);

  Stream<List<int>> readAsBytes() => new Stream.fromIterable([_contents]);

  Future _validate(String prettPath, List<int> actualContents) async {
    if (const IterableEquality().equals(_contents, actualContents)) return null;
    // TODO(nweiz): show a hex dump here if the data is small enough.
    fail('File "$prettPath" didn\'t contain the expected binary data.');
  }
}

class _StringFileDescriptor extends FileDescriptor {
  /// The contents of this descriptor's file.
  final String _contents;

  _StringFileDescriptor(String name, this._contents) : super.protected(name);

  Future<String> read() async => _contents;

  Stream<List<int>> readAsBytes() =>
      new Stream.fromIterable([UTF8.encode(_contents)]);

  Future _validate(String prettyPath, List<int> actualContents) {
    var actualContentsText = UTF8.decode(actualContents);
    if (_contents == actualContentsText) return null;
    throw fail(_textMismatchMessage(prettyPath, _contents, actualContentsText));
  }

  String _textMismatchMessage(String prettyPath, String expected,
      String actual) {
    final expectedLines = expected.split('\n');
    final actualLines = actual.split('\n');

    var results = [];

    // Compare them line by line to see which ones match.
    var length = math.max(expectedLines.length, actualLines.length);
    for (var i = 0; i < length; i++) {
      if (i >= actualLines.length) {
        // Missing output.
        results.add('? ${expectedLines[i]}');
      } else if (i >= expectedLines.length) {
        // Unexpected extra output.
        results.add('X ${actualLines[i]}');
      } else {
        var expectedLine = expectedLines[i];
        var actualLine = actualLines[i];

        if (expectedLine != actualLine) {
          // Mismatched lines.
          results.add('X $actualLine');
        } else {
          // Matched lines.
          results.add('${glyph.verticalLine} $actualLine');
        }
      }
    }

    return 'File "$prettyPath" should contain:\n'
        "${addBar(expected)}\n"
        "but actually contained:\n"
        "${results.join('\n')}";
  }
}

class _MatcherFileDescriptor extends FileDescriptor {
  /// The matcher for this descriptor's contents.
  final Matcher _matcher;

  /// Whether [_matcher] should match against the file's string or byte
  /// contents.
  final bool _isBinary;

  _MatcherFileDescriptor(String name, this._matcher, {bool isBinary: false})
      : _isBinary = isBinary,
        super.protected(name);

  Stream<List<int>> readAsBytes() =>
      throw new UnsupportedError("Matcher files can't be created or read.");

  void _validate(String prettyPath, List<int> actualContents) {
    try {
      expect(
          _isBinary ? actualContents : UTF8.decode(actualContents),
          _matcher);
    } on TestFailure catch (error) {
      throw new TestFailure(
          'Invalid contents for file "$prettyPath":\n' + error.message);
    }
  }
}
