// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import '../artifacts.dart';
import '../base/file_system.dart';
import '../build_info.dart';
import 'build_system.dart';
import 'exceptions.dart';

/// A set of source files.
abstract class ResolvedFiles {
  /// Whether any of the sources we evaluated contained a missing depfile.
  ///
  /// If so, the build system needs to rerun the visitor after executing the
  /// build to ensure all hashes are up to date.
  bool get containsNewDepfile;

  /// The resolved source files.
  List<File> get sources;
}

/// Collects sources for a [Target] into a single list of [FileSystemEntities].
class SourceVisitor implements ResolvedFiles {
  /// Create a new [SourceVisitor] from an [Environment].
  SourceVisitor(this.environment, [ this.inputs = true ]);

  /// The current environment.
  final Environment environment;

  /// Whether we are visiting inputs or outputs.
  ///
  /// Defaults to `true`.
  final bool inputs;

  @override
  final List<File> sources = <File>[];

  @override
  bool get containsNewDepfile => _containsNewDepfile;
  bool _containsNewDepfile = false;

  /// Visit a depfile which contains both input and output files.
  ///
  /// If the file is missing, this visitor is marked as [containsNewDepfile].
  /// This is used by the [Node] class to tell the [BuildSystem] to
  /// defer hash computation until after executing the target.
  // depfile logic adopted from https://github.com/flutter/flutter/blob/7065e4330624a5a216c8ffbace0a462617dc1bf5/dev/devicelab/lib/framework/apk_utils.dart#L390
  void visitDepfile(String name) {
    final File depfile = environment.buildDir.childFile(name);
    if (!depfile.existsSync()) {
      _containsNewDepfile = true;
      return;
    }
    final String contents = depfile.readAsStringSync();
    final List<String> colonSeparated = contents.split(': ');
    if (colonSeparated.length != 2) {
      environment.logger.printError('Invalid depfile: ${depfile.path}');
      return;
    }
    if (inputs) {
      sources.addAll(_processList(colonSeparated[1].trim()));
    } else {
      sources.addAll(_processList(colonSeparated[0].trim()));
    }
  }

  final RegExp _separatorExpr = RegExp(r'([^\\]) ');
  final RegExp _escapeExpr = RegExp(r'\\(.)');

  Iterable<File> _processList(String rawText) {
    return rawText
    // Put every file on right-hand side on the separate line
        .replaceAllMapped(_separatorExpr, (Match match) => '${match.group(1)}\n')
        .split('\n')
    // Expand escape sequences, so that '\ ', for example,ß becomes ' '
        .map<String>((String path) => path.replaceAllMapped(_escapeExpr, (Match match) => match.group(1)).trim())
        .where((String path) => path.isNotEmpty)
        .toSet()
        .map(environment.fileSystem.file);
  }

  /// Visit a [Source] which contains a file URL.
  ///
  /// The URL may include constants defined in an [Environment]. If
  /// [optional] is true, the file is not required to exist. In this case, it
  /// is never resolved as an input.
  void visitPattern(String pattern, bool optional) {
    // perform substitution of the environmental values and then
    // of the local values.
    final List<String> segments = <String>[];
    final List<String> rawParts = pattern.split('/');
    final bool hasWildcard = rawParts.last.contains('*');
    String wildcardFile;
    if (hasWildcard) {
      wildcardFile = rawParts.removeLast();
    }
    // If the pattern does not start with an env variable, then we have nothing
    // to resolve it to, error out.
    switch (rawParts.first) {
      case Environment.kProjectDirectory:
        segments.addAll(
          environment.fileSystem.path.split(environment.projectDir.resolveSymbolicLinksSync()));
        break;
      case Environment.kBuildDirectory:
        segments.addAll(environment.fileSystem.path.split(
          environment.buildDir.resolveSymbolicLinksSync()));
        break;
      case Environment.kCacheDirectory:
        segments.addAll(
          environment.fileSystem.path.split(environment.cacheDir.resolveSymbolicLinksSync()));
        break;
      case Environment.kFlutterRootDirectory:
        // flutter root will not contain a symbolic link.
        segments.addAll(
          environment.fileSystem.path.split(environment.flutterRootDir.absolute.path));
        break;
      case Environment.kOutputDirectory:
        segments.addAll(
          environment.fileSystem.path.split(environment.outputDir.resolveSymbolicLinksSync()));
        break;
      default:
        throw InvalidPatternException(pattern);
    }
    rawParts.skip(1).forEach(segments.add);
    final String filePath = environment.fileSystem.path.joinAll(segments);
    if (!hasWildcard) {
      if (optional && !environment.fileSystem.isFileSync(filePath)) {
        return;
      }
      sources.add(environment.fileSystem.file(
        environment.fileSystem.path.normalize(filePath)));
      return;
    }
    // Perform a simple match by splitting the wildcard containing file one
    // the `*`. For example, for `/*.dart`, we get [.dart]. We then check
    // that part of the file matches. If there are values before and after
    // the `*` we need to check that both match without overlapping. For
    // example, `foo_*_.dart`. We want to match `foo_b_.dart` but not
    // `foo_.dart`. To do so, we first subtract the first section from the
    // string if the first segment matches.
    final List<String> wildcardSegments = wildcardFile.split('*');
    if (wildcardSegments.length > 2) {
      throw InvalidPatternException(pattern);
    }
    if (!environment.fileSystem.directory(filePath).existsSync()) {
      throw Exception('$filePath does not exist!');
    }
    for (final FileSystemEntity entity in environment.fileSystem.directory(filePath).listSync()) {
      final String filename = environment.fileSystem.path.basename(entity.path);
      if (wildcardSegments.isEmpty) {
        sources.add(environment.fileSystem.file(entity.absolute));
      } else if (wildcardSegments.length == 1) {
        if (filename.startsWith(wildcardSegments[0]) ||
            filename.endsWith(wildcardSegments[0])) {
          sources.add(environment.fileSystem.file(entity.absolute));
        }
      } else if (filename.startsWith(wildcardSegments[0])) {
        if (filename.substring(wildcardSegments[0].length).endsWith(wildcardSegments[1])) {
          sources.add(environment.fileSystem.file(entity.absolute));
        }
      }
    }
  }

  /// Visit a [Source] which is defined by an [Artifact] from the flutter cache.
  ///
  /// If the [Artifact] points to a directory then all child files are included.
  /// To increase the performance of builds that use a known revision of Flutter,
  /// these are updated to point towards the engine.version file instead of
  /// the artifact itself.
  void visitArtifact(Artifact artifact, TargetPlatform platform, BuildMode mode) {
    // This is not a local engine.
    if (environment.engineVersion != null) {
      sources.add(environment.flutterRootDir
        .childDirectory('bin')
        .childDirectory('internal')
        .childFile('engine.version'),
      );
      return;
    }
    final String path = environment.artifacts
      .getArtifactPath(artifact, platform: platform, mode: mode);
    if (environment.fileSystem.isDirectorySync(path)) {
      sources.addAll(<File>[
        for (FileSystemEntity entity in environment.fileSystem.directory(path).listSync(recursive: true))
          if (entity is File)
            entity,
      ]);
      return;
    }
    sources.add(environment.fileSystem.file(path));
  }
}

/// A description of an input or output of a [Target].
abstract class Source {
  /// This source is a file URL which contains some references to magic
  /// environment variables.
  const factory Source.pattern(String pattern, { bool optional }) = _PatternSource;
  /// The source is provided by an [Artifact].
  ///
  /// If [artifact] points to a directory then all child files are included.
  const factory Source.artifact(Artifact artifact, {TargetPlatform platform, BuildMode mode}) = _ArtifactSource;

  /// Visit the particular source type.
  void accept(SourceVisitor visitor);

  /// Whether the output source provided can be known before executing the rule.
  ///
  /// This does not apply to inputs, which are always explicit and must be
  /// evaluated before the build.
  ///
  /// For example, [Source.pattern] and [Source.version] are not implicit
  /// provided they do not use any wildcards.
  bool get implicit;
}

class _PatternSource implements Source {
  const _PatternSource(this.value, { this.optional = false });

  final String value;
  final bool optional;

  @override
  void accept(SourceVisitor visitor) => visitor.visitPattern(value, optional);

  @override
  bool get implicit => value.contains('*');
}

class _ArtifactSource implements Source {
  const _ArtifactSource(this.artifact, { this.platform, this.mode });

  final Artifact artifact;
  final TargetPlatform platform;
  final BuildMode mode;

  @override
  void accept(SourceVisitor visitor) => visitor.visitArtifact(artifact, platform, mode);

  @override
  bool get implicit => false;
}
