// 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.

// @dart = 2.8

import '../base/common.dart';
import '../base/file_system.dart';
import '../cache.dart';
import '../globals_null_migrated.dart' as globals;
import '../runner/flutter_command.dart';
import '../template.dart';

class IdeConfigCommand extends FlutterCommand {
  IdeConfigCommand() {
    argParser.addFlag(
      'overwrite',
      negatable: true,
      defaultsTo: false,
      help: 'When performing operations, overwrite existing files.',
    );
    argParser.addFlag(
      'update-templates',
      negatable: false,
      help: 'Update the templates in the template directory from the current '
            'configuration files. This is the opposite of what $name usually does. '
            'Will search the flutter tree for *.iml files and copy any missing ones '
            'into the template directory. If "--overwrite" is also specified, it will '
            'update any out-of-date files, and remove any deleted files from the '
            'template directory.',
    );
    argParser.addFlag(
      'with-root-module',
      negatable: true,
      defaultsTo: true,
      help: 'Also create module that corresponds to the root of Flutter tree. '
            'This makes the entire Flutter tree browsable and searchable in IDE. '
            'Without this flag, only the child modules will be visible in IDE.',
    );
  }

  @override
  final String name = 'ide-config';

  @override
  Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{};

  @override
  final String description = 'Configure the IDE for use in the Flutter tree.\n\n'
      'If run on a Flutter tree that is already configured for the IDE, this '
      'command will add any new configurations, recreate any files that are '
      'missing. If --overwrite is specified, will revert existing files to '
      'the template versions, reset the module list, and return configuration '
      'settings to the template versions.\n\n'
      'This command is intended for Flutter developers to help them set up the '
      "Flutter tree for development in an IDE. It doesn't affect other projects.\n\n"
      'Currently, IntelliJ is the default (and only) IDE that may be configured.';

  @override
  final bool hidden = true;

  @override
  String get invocation => '${runner.executableName} $name';

  static const String _ideName = 'intellij';
  Directory get _templateDirectory {
    return globals.fs.directory(globals.fs.path.join(
      Cache.flutterRoot,
      'packages',
      'flutter_tools',
      'ide_templates',
      _ideName,
    ));
  }

  Directory get _createTemplatesDirectory {
    return globals.fs.directory(globals.fs.path.join(
      Cache.flutterRoot,
      'packages',
      'flutter_tools',
      'templates',
    ));
  }

  Directory get _flutterRoot => globals.fs.directory(globals.fs.path.absolute(Cache.flutterRoot));

  // Returns true if any entire path element is equal to dir.
  bool _hasDirectoryInPath(FileSystemEntity entity, String dir) {
    String path = entity.absolute.path;
    while (path.isNotEmpty && globals.fs.path.dirname(path) != path) {
      if (globals.fs.path.basename(path) == dir) {
        return true;
      }
      path = globals.fs.path.dirname(path);
    }
    return false;
  }

  // Returns true if child is anywhere underneath parent.
  bool _isChildDirectoryOf(FileSystemEntity parent, FileSystemEntity child) {
    return child.absolute.path.startsWith(parent.absolute.path);
  }

  // Checks the contents of the two files to see if they have changes.
  bool _fileIsIdentical(File src, File dest) {
    if (src.lengthSync() != dest.lengthSync()) {
      return false;
    }

    // Test byte by byte. We're assuming that these are small files.
    final List<int> srcBytes = src.readAsBytesSync();
    final List<int> destBytes = dest.readAsBytesSync();
    for (int i = 0; i < srcBytes.length; ++i) {
      if (srcBytes[i] != destBytes[i]) {
        return false;
      }
    }
    return true;
  }

  // Discovers and syncs with existing configuration files in the Flutter tree.
  void _handleTemplateUpdate() {
    if (!_flutterRoot.existsSync()) {
      return;
    }

    final Set<String> manifest = <String>{};
    final Iterable<File> flutterFiles = _flutterRoot.listSync(recursive: true).whereType<File>();
    for (final File srcFile in flutterFiles) {
      final String relativePath = globals.fs.path.relative(srcFile.path, from: _flutterRoot.absolute.path);

      // Skip template files in both the ide_templates and templates
      // directories to avoid copying onto themselves.
      if (_isChildDirectoryOf(_templateDirectory, srcFile) ||
          _isChildDirectoryOf(_createTemplatesDirectory, srcFile)) {
        continue;
      }

      // Skip files we aren't interested in.
      final RegExp _trackedIdeaFileRegExp = RegExp(
        r'(\.name|modules.xml|vcs.xml)$',
      );
      final bool isATrackedIdeaFile = _hasDirectoryInPath(srcFile, '.idea') &&
          (_trackedIdeaFileRegExp.hasMatch(relativePath) ||
              _hasDirectoryInPath(srcFile, 'runConfigurations'));
      final bool isAnImlOutsideIdea = !isATrackedIdeaFile && srcFile.path.endsWith('.iml');
      if (!isATrackedIdeaFile && !isAnImlOutsideIdea) {
        continue;
      }

      final File finalDestinationFile = globals.fs.file(globals.fs.path.absolute(
          _templateDirectory.absolute.path, '$relativePath${Template.copyTemplateExtension}'));
      final String relativeDestination =
          globals.fs.path.relative(finalDestinationFile.path, from: _flutterRoot.absolute.path);
      if (finalDestinationFile.existsSync()) {
        if (_fileIsIdentical(srcFile, finalDestinationFile)) {
          globals.printTrace('  $relativeDestination (identical)');
          manifest.add('$relativePath${Template.copyTemplateExtension}');
          continue;
        }
        if (boolArg('overwrite')) {
          finalDestinationFile.deleteSync();
          globals.printStatus('  $relativeDestination (overwritten)');
        } else {
          globals.printTrace('  $relativeDestination (existing - skipped)');
          manifest.add('$relativePath${Template.copyTemplateExtension}');
          continue;
        }
      } else {
        globals.printStatus('  $relativeDestination (added)');
      }
      final Directory finalDestinationDir = globals.fs.directory(finalDestinationFile.dirname);
      if (!finalDestinationDir.existsSync()) {
        globals.printTrace("  ${finalDestinationDir.path} doesn't exist, creating.");
        finalDestinationDir.createSync(recursive: true);
      }
      srcFile.copySync(finalDestinationFile.path);
      manifest.add('$relativePath${Template.copyTemplateExtension}');
    }

    // If we're not overwriting, then we're not going to remove missing items either.
    if (!boolArg('overwrite')) {
      return;
    }

    // Look for any files under the template dir that don't exist in the manifest and remove
    // them.
    final Iterable<File> templateFiles = _templateDirectory.listSync(recursive: true).whereType<File>();
    for (final File templateFile in templateFiles) {
      final String relativePath = globals.fs.path.relative(
        templateFile.absolute.path,
        from: _templateDirectory.absolute.path,
      );
      if (!manifest.contains(relativePath)) {
        templateFile.deleteSync();
        final String relativeDestination =
            globals.fs.path.relative(templateFile.path, from: _flutterRoot.absolute.path);
        globals.printStatus('  $relativeDestination (removed)');
      }
      // If the directory is now empty, then remove it, and do the same for its parent,
      // until we escape to the template directory.
      Directory parentDir = globals.fs.directory(templateFile.dirname);
      while (parentDir.listSync().isEmpty) {
        parentDir.deleteSync();
        globals.printTrace('  ${globals.fs.path.relative(parentDir.absolute.path)} (empty directory - removed)');
        parentDir = globals.fs.directory(parentDir.dirname);
        if (globals.fs.path.isWithin(_templateDirectory.absolute.path, parentDir.absolute.path)) {
          break;
        }
      }
    }
  }

  @override
  Future<FlutterCommandResult> runCommand() async {
    if (argResults.rest.isNotEmpty) {
      throwToolExit('Currently, the only supported IDE is IntelliJ\n$usage', exitCode: 2);
    }

    if (boolArg('update-templates')) {
      _handleTemplateUpdate();
      return FlutterCommandResult.success();
    }

    final String flutterRoot = globals.fs.path.absolute(Cache.flutterRoot);
    final String dirPath = globals.fs.path.normalize(
      globals.fs.directory(globals.fs.path.absolute(Cache.flutterRoot)).absolute.path,
    );

    final String error = _validateFlutterDir(dirPath, flutterRoot: flutterRoot);
    if (error != null) {
      throwToolExit(error);
    }

    globals.printStatus('Updating IDE configuration for Flutter tree at $dirPath...');
    int generatedCount = 0;
    generatedCount += _renderTemplate(_ideName, dirPath, <String, Object>{
      'withRootModule': boolArg('with-root-module'),
      'android': true,
    });

    globals.printStatus('Wrote $generatedCount files.');
    globals.printStatus('');
    globals.printStatus('Your IntelliJ configuration is now up to date. It is prudent to '
        'restart IntelliJ, if running.');

    return FlutterCommandResult.success();
  }

  int _renderTemplate(String templateName, String dirPath, Map<String, Object> context) {
    final Template template = Template(
      _templateDirectory,
      null,
      fileSystem: globals.fs,
      logger: globals.logger,
      templateRenderer: globals.templateRenderer,
    );
    return template.render(
      globals.fs.directory(dirPath),
      context,
      overwriteExisting: boolArg('overwrite'),
    );
  }
}

/// Return null if the flutter root directory is a valid destination. Return a
/// validation message if we should disallow the directory.
String _validateFlutterDir(String dirPath, { String flutterRoot }) {
  final FileSystemEntityType type = globals.fs.typeSync(dirPath);

  switch (type) { // ignore: exhaustive_cases, https://github.com/dart-lang/linter/issues/3017
    case FileSystemEntityType.link:
      // Do not overwrite links.
      return "Invalid project root dir: '$dirPath' - refers to a link.";
    case FileSystemEntityType.file:
    case FileSystemEntityType.directory:
    case FileSystemEntityType.notFound:
      return null;
  }
  return null; // dead code, remove after null safety migration
}
