// 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 '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_null_migrated.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', () {
    Directory tempDir;
    Directory templateDir;
    Directory intellijDir;
    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,
      );
    });

  });
}
