// 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 'package:meta/meta.dart';
import 'package:package_config/package_config.dart';
import 'package:package_config/package_config_types.dart';

import 'base/common.dart';
import 'base/file_system.dart';
import 'base/logger.dart';
import 'base/template.dart';
import 'cache.dart';
import 'dart/package_map.dart';
import 'dart/pub.dart';

/// Expands templates in a directory to a destination. All files that must
/// undergo template expansion should end with the '.tmpl' extension. All files
/// that should be replaced with the corresponding image from
/// flutter_template_images should end with the '.img.tmpl' extension. All other
/// files are ignored. In case the contents of entire directories must be copied
/// as is, the directory itself can end with '.tmpl' extension. Files within
/// such a directory may also contain the '.tmpl' or '.img.tmpl' extensions and
/// will be considered for expansion. In case certain files need to be copied
/// but without template expansion (data files, etc.), the '.copy.tmpl'
/// extension may be used.
///
/// Folders with platform/language-specific content must be named
/// '<platform>-<language>.tmpl'.
///
/// Files in the destination will contain none of the '.tmpl', '.copy.tmpl',
/// 'img.tmpl', or '-<language>.tmpl' extensions.
class Template {
  Template(Directory templateSource, Directory baseDir, this.imageSourceDir, {
    @required FileSystem fileSystem,
    @required Logger logger,
    @required TemplateRenderer templateRenderer,
    @required Set<Uri> templateManifest,
  }) : _fileSystem = fileSystem,
       _logger = logger,
       _templateRenderer = templateRenderer,
       _templateManifest = templateManifest {
    _templateFilePaths = <String, String>{};

    if (!templateSource.existsSync()) {
      return;
    }

    final List<FileSystemEntity> templateFiles = templateSource.listSync(recursive: true);
    for (final FileSystemEntity entity in templateFiles.whereType<File>()) {
      if (_templateManifest != null && !_templateManifest.contains(Uri.file(entity.absolute.path))) {
        _logger.printTrace('Skipping ${entity.absolute.path}, missing from the template manifest.');
        // Skip stale files in the flutter_tools directory.
        continue;
      }

      final String relativePath = fileSystem.path.relative(entity.path,
          from: baseDir.absolute.path);
      if (relativePath.contains(templateExtension)) {
        // If '.tmpl' appears anywhere within the path of this entity, it is
        // is a candidate for rendering. This catches cases where the folder
        // itself is a template.
        _templateFilePaths[relativePath] = fileSystem.path.absolute(entity.path);
      }
    }
  }

  static Future<Template> fromName(String name, {
    @required FileSystem fileSystem,
    @required Set<Uri> templateManifest,
    @required Logger logger,
    @required TemplateRenderer templateRenderer,
    @required Pub pub,
  }) async {
    // All named templates are placed in the 'templates' directory
    final Directory templateDir = _templateDirectoryInPackage(name, fileSystem);
    final Directory imageDir = await _templateImageDirectory(name, fileSystem, logger, pub);
    return Template(
      templateDir,
      templateDir, imageDir,
      fileSystem: fileSystem,
      logger: logger,
      templateRenderer: templateRenderer,
      templateManifest: templateManifest,
    );
  }

  final FileSystem _fileSystem;
  final Logger _logger;
  final Set<Uri> _templateManifest;
  final TemplateRenderer _templateRenderer;

  static const String templateExtension = '.tmpl';
  static const String copyTemplateExtension = '.copy.tmpl';
  static const String imageTemplateExtension = '.img.tmpl';
  final Pattern _kTemplateLanguageVariant = RegExp(r'(\w+)-(\w+)\.tmpl.*');
  final Directory imageSourceDir;

  Map<String /* relative */, String /* absolute source */> _templateFilePaths;

  /// Render the template into [directory].
  ///
  /// May throw a [ToolExit] if the directory is not writable.
  int render(
    Directory destination,
    Map<String, dynamic> context, {
    bool overwriteExisting = true,
    bool printStatusWhenWriting = true,
  }) {
    try {
      destination.createSync(recursive: true);
    } on FileSystemException catch (err) {
      _logger.printError(err.toString());
      throwToolExit('Failed to flutter create at ${destination.path}.');
      return 0;
    }
    int fileCount = 0;

    /// Returns the resolved destination path corresponding to the specified
    /// raw destination path, after performing language filtering and template
    /// expansion on the path itself.
    ///
    /// Returns null if the given raw destination path has been filtered.
    String renderPath(String relativeDestinationPath) {
      final Match match = _kTemplateLanguageVariant.matchAsPrefix(relativeDestinationPath);
      if (match != null) {
        final String platform = match.group(1);
        final String language = context['${platform}Language'] as String;
        if (language != match.group(2)) {
          return null;
        }
        relativeDestinationPath = relativeDestinationPath.replaceAll('$platform-$language.tmpl', platform);
      }

      final bool android = context['android'] as bool;
      if (relativeDestinationPath.contains('android') && !android) {
        return null;
      }

      final bool ios = context['ios'] as bool;
      if (relativeDestinationPath.contains('ios') && !ios) {
        return null;
      }

      // Only build a web project if explicitly asked.
      final bool web = context['web'] as bool;
      if (relativeDestinationPath.contains('web') && !web) {
        return null;
      }
      // Only build a Linux project if explicitly asked.
      final bool linux = context['linux'] as bool;
      if (relativeDestinationPath.startsWith('linux.tmpl') && !linux) {
        return null;
      }
      // Only build a macOS project if explicitly asked.
      final bool macOS = context['macos'] as bool;
      if (relativeDestinationPath.startsWith('macos.tmpl') && !macOS) {
        return null;
      }
      // Only build a Windows project if explicitly asked.
      final bool windows = context['windows'] as bool;
      if (relativeDestinationPath.startsWith('windows.tmpl') && !windows) {
        return null;
      }

      final String projectName = context['projectName'] as String;
      final String androidIdentifier = context['androidIdentifier'] as String;
      final String pluginClass = context['pluginClass'] as String;
      final String pluginClassSnakeCase = context['pluginClassSnakeCase'] as String;
      final String destinationDirPath = destination.absolute.path;
      final String pathSeparator = _fileSystem.path.separator;
      String finalDestinationPath = _fileSystem.path
        .join(destinationDirPath, relativeDestinationPath)
        .replaceAll(copyTemplateExtension, '')
        .replaceAll(imageTemplateExtension, '')
        .replaceAll(templateExtension, '');

      if (android != null && android && androidIdentifier != null) {
        finalDestinationPath = finalDestinationPath
            .replaceAll('androidIdentifier', androidIdentifier.replaceAll('.', pathSeparator));
      }
      if (projectName != null) {
        finalDestinationPath = finalDestinationPath.replaceAll('projectName', projectName);
      }
      // This must be before the pluginClass replacement step.
      if (pluginClassSnakeCase != null) {
        finalDestinationPath = finalDestinationPath.replaceAll('pluginClassSnakeCase', pluginClassSnakeCase);
      }
      if (pluginClass != null) {
        finalDestinationPath = finalDestinationPath.replaceAll('pluginClass', pluginClass);
      }
      return finalDestinationPath;
    }

    _templateFilePaths.forEach((String relativeDestinationPath, String absoluteSourcePath) {
      final bool withRootModule = context['withRootModule'] as bool ?? false;
      if (!withRootModule && absoluteSourcePath.contains('flutter_root')) {
        return;
      }

      final String finalDestinationPath = renderPath(relativeDestinationPath);
      if (finalDestinationPath == null) {
        return;
      }
      final File finalDestinationFile = _fileSystem.file(finalDestinationPath);
      final String relativePathForLogging = _fileSystem.path.relative(finalDestinationFile.path);

      // Step 1: Check if the file needs to be overwritten.

      if (finalDestinationFile.existsSync()) {
        if (overwriteExisting) {
          finalDestinationFile.deleteSync(recursive: true);
          if (printStatusWhenWriting) {
            _logger.printStatus('  $relativePathForLogging (overwritten)');
          }
        } else {
          // The file exists but we cannot overwrite it, move on.
          if (printStatusWhenWriting) {
            _logger.printTrace('  $relativePathForLogging (existing - skipped)');
          }
          return;
        }
      } else {
        if (printStatusWhenWriting) {
          _logger.printStatus('  $relativePathForLogging (created)');
        }
      }

      fileCount += 1;

      finalDestinationFile.createSync(recursive: true);
      final File sourceFile = _fileSystem.file(absoluteSourcePath);

      // Step 2: If the absolute paths ends with a '.copy.tmpl', this file does
      //         not need mustache rendering but needs to be directly copied.

      if (sourceFile.path.endsWith(copyTemplateExtension)) {
        _validateReadPermissions(sourceFile);
        sourceFile.copySync(finalDestinationFile.path);

        return;
      }

      // Step 3: If the absolute paths ends with a '.img.tmpl', this file needs
      //         to be copied from the template image package.

      if (sourceFile.path.endsWith(imageTemplateExtension)) {
        final File imageSourceFile = _fileSystem.file(_fileSystem.path.join(
            imageSourceDir.path, relativeDestinationPath.replaceAll(imageTemplateExtension, '')));
        _validateReadPermissions(imageSourceFile);
        imageSourceFile.copySync(finalDestinationFile.path);

        return;
      }

      // Step 4: If the absolute path ends with a '.tmpl', this file needs
      //         rendering via mustache.

      if (sourceFile.path.endsWith(templateExtension)) {
         _validateReadPermissions(sourceFile);
        final String templateContents = sourceFile.readAsStringSync();
        final String renderedContents = _templateRenderer.renderString(templateContents, context);

        finalDestinationFile.writeAsStringSync(renderedContents);

        return;
      }

      // Step 5: This file does not end in .tmpl but is in a directory that
      //         does. Directly copy the file to the destination.
      _validateReadPermissions(sourceFile);
      sourceFile.copySync(finalDestinationFile.path);
    });

    return fileCount;
  }

  /// Attempt open/close the file to ensure that read permissions are correct.
  ///
  /// If this fails with a certain error code, the [ErrorHandlingFileSystem] will
  /// trigger a tool exit with a better message.
  void _validateReadPermissions(File file) {
    file.openSync().closeSync();
  }
}

Directory _templateDirectoryInPackage(String name, FileSystem fileSystem) {
  final String templatesDir = fileSystem.path.join(Cache.flutterRoot,
      'packages', 'flutter_tools', 'templates');
  return fileSystem.directory(fileSystem.path.join(templatesDir, name));
}

// Returns the directory containing the 'name' template directory in
// flutter_template_images, to resolve image placeholder against.
Future<Directory> _templateImageDirectory(String name, FileSystem fileSystem, Logger logger, Pub pub) async {
  final String toolPackagePath = fileSystem.path.join(
      Cache.flutterRoot, 'packages', 'flutter_tools');
  final String packageFilePath = fileSystem.path.join(toolPackagePath, kPackagesFileName);
  final PackageConfig packageConfig = await loadPackageConfigWithLogging(
    fileSystem.file(packageFilePath),
    logger: logger,
  );
  final Uri imagePackageLibDir = packageConfig['flutter_template_images']?.packageUriRoot;
  return fileSystem.directory(imagePackageLibDir)
      .parent
      .childDirectory('templates')
      .childDirectory(name);
}
