// 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:args/command_runner.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/ide_config.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/template.dart';

import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/test_flutter_command_runner.dart';

void main() {
  group('ide_config', () {
    late Directory tempDir;
    late Directory templateDir;
    late Directory intellijDir;
    late Directory toolsDir;

    Map<String, String> getFilesystemContents([ Directory? root ]) {
      final String tempPath = tempDir.absolute.path;
      final List<String> paths =
        (root ?? tempDir).listSync(recursive: true).map((FileSystemEntity entity) {
          final String relativePath = globals.fs.path.relative(entity.path, from: tempPath);
          return relativePath;
        }).toList();
      final Map<String, String> contents = <String, String>{};
      for (final String path in paths) {
        final String absPath = globals.fs.path.join(tempPath, path);
        if (globals.fs.isDirectorySync(absPath)) {
          contents[path] = 'dir';
        } else if (globals.fs.isFileSync(absPath)) {
          contents[path] = globals.fs.file(absPath).readAsStringSync();
        }
      }
      return contents;
    }

    Map<String, String> getManifest(Directory base, String marker, { bool isTemplate = false }) {
      final String basePath = globals.fs.path.relative(base.path, from: tempDir.absolute.path);
      final String suffix = isTemplate ? Template.copyTemplateExtension : '';
      return <String, String>{
        globals.fs.path.join(basePath, '.idea'): 'dir',
        globals.fs.path.join(basePath, '.idea', 'modules.xml$suffix'): 'modules $marker',
        globals.fs.path.join(basePath, '.idea', 'vcs.xml$suffix'): 'vcs $marker',
        globals.fs.path.join(basePath, '.idea', '.name$suffix'): 'codeStyleSettings $marker',
        globals.fs.path.join(basePath, '.idea', 'runConfigurations'): 'dir',
        globals.fs.path.join(basePath, '.idea', 'runConfigurations', 'hello_world.xml$suffix'): 'hello_world $marker',
        globals.fs.path.join(basePath, 'flutter.iml$suffix'): 'flutter $marker',
        globals.fs.path.join(basePath, 'packages', 'new', 'deep.iml$suffix'): 'deep $marker',
        globals.fs.path.join(basePath, 'example', 'gallery', 'android.iml$suffix'): 'android $marker',
      };
    }

    void populateDir(Map<String, String> manifest) {
      for (final String key in manifest.keys) {
        if (manifest[key] == 'dir') {
          tempDir.childDirectory(key).createSync(recursive: true);
        }
      }
      for (final String key in manifest.keys) {
        if (manifest[key] != 'dir') {
          tempDir.childFile(key)
            ..createSync(recursive: true)
            ..writeAsStringSync(manifest[key]!);
        }
      }
    }

    bool fileOrDirectoryExists(String path) {
      final String absPath = globals.fs.path.join(tempDir.absolute.path, path);
      return globals.fs.file(absPath).existsSync() || globals.fs.directory(absPath).existsSync();
    }

    Future<void> updateIdeConfig({
      Directory? dir,
      List<String> args = const <String>[],
      Map<String, String> expectedContents = const <String, String>{},
      List<String> unexpectedPaths = const <String>[],
    }) async {
      dir ??= tempDir;
      Cache.flutterRoot = tempDir.absolute.path;
      final IdeConfigCommand command = IdeConfigCommand();
      final CommandRunner<void> runner = createTestCommandRunner(command);
      await runner.run(<String>[
        'ide-config',
        ...args,
      ]);

      for (final String path in expectedContents.keys) {
        final String absPath = globals.fs.path.join(tempDir.absolute.path, path);
        expect(fileOrDirectoryExists(globals.fs.path.join(dir.path, path)), true,
            reason: "$path doesn't exist");
        if (globals.fs.file(absPath).existsSync()) {
          expect(globals.fs.file(absPath).readAsStringSync(), equals(expectedContents[path]),
              reason: "$path contents don't match");
        }
      }
      for (final String path in unexpectedPaths) {
        expect(fileOrDirectoryExists(globals.fs.path.join(dir.path, path)), false, reason: '$path exists');
      }
    }

    setUpAll(() {
      Cache.disableLocking();
    });

    setUp(() {
      tempDir = globals.fs.systemTempDirectory.createTempSync('flutter_tools_ide_config_test.');
      final Directory packagesDir = tempDir.childDirectory('packages')..createSync(recursive: true);
      toolsDir = packagesDir.childDirectory('flutter_tools')..createSync();
      templateDir = toolsDir.childDirectory('ide_templates')..createSync();
      intellijDir = templateDir.childDirectory('intellij')..createSync();
    });

    tearDown(() {
      tryToDelete(tempDir);
    });

    testUsingContext("doesn't touch existing files without --overwrite", () async {
      final Map<String, String> templateManifest = getManifest(
        intellijDir,
        'template',
        isTemplate: true,
      );
      final Map<String, String> flutterManifest = getManifest(
        tempDir,
        'existing',
      );
      populateDir(templateManifest);
      populateDir(flutterManifest);
      final Map<String, String> expectedContents = getFilesystemContents();
      return updateIdeConfig(
        expectedContents: expectedContents,
      );
    });

    testUsingContext('creates non-existent files', () async {
      final Map<String, String> templateManifest = getManifest(
        intellijDir,
        'template',
        isTemplate: true,
      );
      final Map<String, String> flutterManifest = getManifest(
        tempDir,
        'template',
      );
      populateDir(templateManifest);
      final Map<String, String> expectedContents = <String, String>{
        ...templateManifest,
        ...flutterManifest,
      };
      return updateIdeConfig(
        expectedContents: expectedContents,
      );
    });

    testUsingContext('overwrites existing files with --overwrite', () async {
      final Map<String, String> templateManifest = getManifest(
        intellijDir,
        'template',
        isTemplate: true,
      );
      final Map<String, String> flutterManifest = getManifest(
        tempDir,
        'existing',
      );
      populateDir(templateManifest);
      populateDir(flutterManifest);
      final Map<String, String> overwrittenManifest = getManifest(
        tempDir,
        'template',
      );
      final Map<String, String> expectedContents = <String, String>{
        ...templateManifest,
        ...overwrittenManifest,
      };
      return updateIdeConfig(
        args: <String>['--overwrite'],
        expectedContents: expectedContents,
      );
    });

    testUsingContext('only adds new templates without --overwrite', () async {
      final Map<String, String> templateManifest = getManifest(
        intellijDir,
        'template',
        isTemplate: true,
      );
      final String flutterIml = globals.fs.path.join(
        'packages',
        'flutter_tools',
        'ide_templates',
        'intellij',
        'flutter.iml${Template.copyTemplateExtension}',
      );
      templateManifest.remove(flutterIml);
      populateDir(templateManifest);
      templateManifest[flutterIml] = 'flutter existing';
      final Map<String, String> flutterManifest = getManifest(
        tempDir,
        'existing',
      );
      populateDir(flutterManifest);
      final Map<String, String> expectedContents = <String, String>{
        ...flutterManifest,
        ...templateManifest,
      };
      return updateIdeConfig(
        args: <String>['--update-templates'],
        expectedContents: expectedContents,
      );
    });

    testUsingContext('update all templates with --overwrite', () async {
      final Map<String, String> templateManifest = getManifest(
        intellijDir,
        'template',
        isTemplate: true,
      );
      populateDir(templateManifest);
      final Map<String, String> flutterManifest = getManifest(
        tempDir,
        'existing',
      );
      populateDir(flutterManifest);
      final Map<String, String> updatedTemplates = getManifest(
        intellijDir,
        'existing',
        isTemplate: true,
      );
      final Map<String, String> expectedContents = <String, String>{
        ...flutterManifest,
        ...updatedTemplates,
      };
      return updateIdeConfig(
        args: <String>['--update-templates', '--overwrite'],
        expectedContents: expectedContents,
      );
    });

    testUsingContext('removes deleted imls with --overwrite', () async {
      final Map<String, String> templateManifest = getManifest(
        intellijDir,
        'template',
        isTemplate: true,
      );
      populateDir(templateManifest);
      final Map<String, String> flutterManifest = getManifest(
        tempDir,
        'existing',
      );
      flutterManifest.remove('flutter.iml');
      populateDir(flutterManifest);
      final Map<String, String> updatedTemplates = getManifest(
        intellijDir,
        'existing',
        isTemplate: true,
      );
      final String flutterIml = globals.fs.path.join(
        'packages',
        'flutter_tools',
        'ide_templates',
        'intellij',
        'flutter.iml${Template.copyTemplateExtension}',
      );
      updatedTemplates.remove(flutterIml);
      final Map<String, String> expectedContents = <String, String>{
        ...flutterManifest,
        ...updatedTemplates,
      };
      return updateIdeConfig(
        args: <String>['--update-templates', '--overwrite'],
        expectedContents: expectedContents,
      );
    });

    testUsingContext('removes deleted imls with --overwrite, including empty parent dirs', () async {
      final Map<String, String> templateManifest = getManifest(
        intellijDir,
        'template',
        isTemplate: true,
      );
      populateDir(templateManifest);
      final Map<String, String> flutterManifest = getManifest(
        tempDir,
        'existing',
      );
      flutterManifest.remove(globals.fs.path.join('packages', 'new', 'deep.iml'));
      populateDir(flutterManifest);
      final Map<String, String> updatedTemplates = getManifest(
        intellijDir,
        'existing',
        isTemplate: true,
      );
      String deepIml = globals.fs.path.join(
        'packages',
        'flutter_tools',
        'ide_templates',
        'intellij');
      // Remove the all the dir entries too.
      updatedTemplates.remove(deepIml);
      deepIml = globals.fs.path.join(deepIml, 'packages');
      updatedTemplates.remove(deepIml);
      deepIml = globals.fs.path.join(deepIml, 'new');
      updatedTemplates.remove(deepIml);
      deepIml = globals.fs.path.join(deepIml, 'deep.iml');
      updatedTemplates.remove(deepIml);
      final Map<String, String> expectedContents = <String, String>{
        ...flutterManifest,
        ...updatedTemplates,
      };
      return updateIdeConfig(
        args: <String>['--update-templates', '--overwrite'],
        expectedContents: expectedContents,
      );
    });

  });
}
