// 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 '../base/common.dart';
import '../base/file_system.dart';
import '../cache.dart';
import '../globals.dart' as globals;
import '../runner/flutter_command.dart';
import '../template.dart';

class IdeConfigCommand extends FlutterCommand {
  IdeConfigCommand() {
    argParser.addFlag(
      'overwrite',
      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',
      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 {
    final List<String> rest = argResults?.rest ?? <String>[];
    if (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;
  }
  // In the case of any other [FileSystemEntityType]s, like the deprecated ones, return null.
  return null;
}
