// 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 '../base/common.dart';
import '../base/file_system.dart';
import '../convert.dart';
import '../plugins.dart';
import '../project.dart';
import 'visual_studio_project.dart';

// Constants corresponding to specific reference types in a solution file.
// These values are defined by the .sln format.
const String _kSolutionTypeGuidFolder = '2150E333-8FDC-42A3-9474-1A3956D46DE8';
const String _kSolutionTypeGuidVcxproj = '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942';

// The GUID for the folder above, managed by this class. This is an arbitrary
// value that was randomly generated, but it should not be changed since that
// would cause issues for existing Flutter projects.
const String _kFlutterPluginSolutionFolderGuid = '5C2E738A-1DD3-445A-AAC8-EEB9648DD07C';
// The FlutterBuild project GUID. This is an arbitrary
// value that was randomly generated, but it should not be changed since that
// would cause issues for existing Flutter projects.
const String _kFlutterBuildProjectGuid = '6419BF13-6ECD-4CD2-9E85-E566A1F03F8F';

/// Extracts and stores the plugin name and vcxproj GUID for [plugin].
class _PluginProjectInfo {
  _PluginProjectInfo(Plugin plugin, {
    @required FileSystem fileSystem,
  }) {
    name = plugin.name;
    final File projectFile = fileSystem.directory(plugin.path).childDirectory('windows').childFile('plugin.vcxproj');
    try {
    guid = VisualStudioProject(projectFile, fileSystem: fileSystem).guid;
    } on FileSystemException {
      throwToolExit('Unable to find a plugin.vcxproj for plugin "$name"');
    }
    if (guid == null) {
      throwToolExit('Unable to find a plugin.vcxproj ID for plugin "$name"');
    }
  }

  // The name of the plugin, which is also the name of the symlink folder.
  String name;

  // The GUID of the plugin's project.
  String guid;
}

// TODO(stuartmorgan): Consider replacing this class with a real parser. See
// https://github.com/flutter/flutter/issues/51430.

class VisualStudioSolutionUtils {
  const VisualStudioSolutionUtils({
    @required WindowsProject project,
    @required FileSystem fileSystem,
  }) : _project = project,
       _fileSystem = fileSystem;

  final WindowsProject _project;
  final FileSystem _fileSystem;

  /// Updates the solution file for [project] to have the project references and
  /// dependencies to include [plugins], removing any previous plugins from the
  /// solution.
  Future<void> updatePlugins(List<Plugin> plugins) async {
    if (!_project.solutionFile.existsSync()) {
      throwToolExit(
        'Attempted to update Windows plugins on a project that does not '
        'support Windows.',
      );
    }
    final String solutionContent = await _project.solutionFile.readAsString();

    // Map of GUID to name for the current plugin list.
    final Map<String, String> currentPluginInfo = _getWindowsPluginNamesByGuid(plugins);

    // Find any plugins referenced in the project that are no longer used, and
    // any that are new.
    //
    // While the simplest approach to updating the solution would be to remove all
    // entries associated with plugins, and then add all the current plugins in
    // one block, Visual Studio has its own (unknown, likely data-structure-hash
    // based) order that it will use each time it writes out the file due to any
    // solution-level changes made in the UI. To avoid thrashing, and resulting
    // confusion (e.g., in review diffs), this update attempts to instead preserve
    // the ordering that is already there, so that once Visual Studio has
    // reordered the plugins, that order will be stable.
    final Set<String> existingPlugins = _findPreviousPluginGuids(solutionContent);
    final Set<String> currentPlugins = currentPluginInfo.keys.toSet();
    final Set<String> removedPlugins = existingPlugins.difference(currentPlugins);
    final Set<String> addedPlugins = currentPlugins.difference(existingPlugins);

    final RegExp projectStartPattern = RegExp(r'^Project\("{' + _kSolutionTypeGuidVcxproj + r'}"\)\s*=\s*".*",\s*"(.*)",\s*"{([A-Fa-f0-9\-]*)}"\s*$');
    final RegExp pluginsFolderProjectStartPattern = RegExp(r'^Project\("{' + _kSolutionTypeGuidFolder + r'}"\)\s*=.*"{' + _kFlutterPluginSolutionFolderGuid + r'}"\s*$');
    final RegExp projectEndPattern = RegExp(r'^EndProject\s*$');
    final RegExp globalStartPattern = RegExp(r'^Global\s*$');
    final RegExp globalEndPattern = RegExp(r'^EndGlobal\s*$');
    final RegExp projectDependenciesStartPattern = RegExp(r'^\s*ProjectSection\(ProjectDependencies\)\s*=\s*postProject\s*$');
    final RegExp globalSectionProjectConfigurationStartPattern = RegExp(r'^\s*GlobalSection\(ProjectConfigurationPlatforms\)\s*=\s*postSolution\s*$');
    final RegExp globalSectionNestedProjectsStartPattern = RegExp(r'^\s*GlobalSection\(NestedProjects\)\s*=\s*preSolution\s*$');

    final StringBuffer newSolutionContent = StringBuffer();
    // readAsString drops the BOM; re-add it.
    newSolutionContent.writeCharCode(unicodeBomCharacterRune);

    final Iterator<String> lineIterator = solutionContent.split('\n').iterator;
    bool foundFlutterPluginsFolder = false;
    bool foundNestedProjectsSection = false;
    bool foundRunnerProject = false;
    while (lineIterator.moveNext()) {
      final Match projectStartMatch = projectStartPattern.firstMatch(lineIterator.current);
      if (projectStartMatch != null) {
        final String guid = projectStartMatch.group(2);
        if (currentPlugins.contains(guid)) {
          // Write an up-to-date version at this location (in case, e.g., the name
          // has changed).
          _writePluginProjectEntry(guid, currentPluginInfo[guid], newSolutionContent);
          // Drop the old copy.
          _skipUntil(lineIterator, projectEndPattern);
          continue;
        } else if (removedPlugins.contains(guid)) {
          // Drop the stale plugin project.
          _skipUntil(lineIterator, projectEndPattern);
          continue;
        } else if (projectStartMatch.group(1) == _project.vcprojFile.basename) {
          foundRunnerProject = true;
          // Update the Runner project's dependencies on the plugins.
          // Skip to the dependencies section, or if there isn't one the end of
          // the project.
          while (!projectDependenciesStartPattern.hasMatch(lineIterator.current) &&
              !projectEndPattern.hasMatch(lineIterator.current)) {
            newSolutionContent.writeln(lineIterator.current);
            lineIterator.moveNext();
          }
          // Add/update the dependencies section.
          if (projectDependenciesStartPattern.hasMatch(lineIterator.current)) {
            newSolutionContent.writeln(lineIterator.current);
            _processSectionPluginReferences(removedPlugins, addedPlugins, lineIterator, _writeProjectDependency, newSolutionContent);
          } else {
            _writeDependenciesSection(currentPlugins, newSolutionContent);
          }
        }
      }

      if (pluginsFolderProjectStartPattern.hasMatch(lineIterator.current)) {
          foundFlutterPluginsFolder = true;
      }

      if (globalStartPattern.hasMatch(lineIterator.current)) {
        // The Global section is the end of the project list. Add any new plugins
        // here, since the location VS will use is unknown. They will likely be
        // reordered the next time VS writes the file.
        for (final String guid in addedPlugins) {
          _writePluginProjectEntry(guid, currentPluginInfo[guid], newSolutionContent);
        }
        // Also add the plugins folder if there wasn't already one.
        if (!foundFlutterPluginsFolder) {
          _writePluginFolderProjectEntry(newSolutionContent);
        }
      }

      // Update the ProjectConfiguration section once it is reached.
      if (globalSectionProjectConfigurationStartPattern.hasMatch(lineIterator.current)) {
        newSolutionContent.writeln(lineIterator.current);
        _processSectionPluginReferences(removedPlugins, addedPlugins, lineIterator, _writePluginConfigurationEntries, newSolutionContent);
      }

      // Update the NestedProjects section once it is reached.
      if (globalSectionNestedProjectsStartPattern.hasMatch(lineIterator.current)) {
        newSolutionContent.writeln(lineIterator.current);
        _processSectionPluginReferences(removedPlugins, addedPlugins, lineIterator, _writePluginNestingEntry, newSolutionContent);
        foundNestedProjectsSection = true;
      }

      // If there wasn't a NestedProjects global section, add one at the end.
      if (!foundNestedProjectsSection && globalEndPattern.hasMatch(lineIterator.current)) {
        newSolutionContent.writeln('\tGlobalSection(NestedProjects) = preSolution\r');
        for (final String guid in currentPlugins) {
          _writePluginNestingEntry(guid, newSolutionContent);
        }
        newSolutionContent.writeln('\tEndGlobalSection\r');
      }

      // Re-output anything that hasn't been explicitly skipped above.
      newSolutionContent.writeln(lineIterator.current);
    }

    if (!foundRunnerProject) {
      throwToolExit(
          'Could not add plugins to Windows project:\n'
          'Unable to find a "${_project.vcprojFile.basename}" project in ${_project.solutionFile.path}');
    }

    await _project.solutionFile.writeAsString(newSolutionContent.toString().trimRight());
  }

  /// Advances [iterator] it reaches an element that matches [pattern].
  ///
  /// Note that the current element at the time of calling is *not* checked.
  void _skipUntil(Iterator<String> iterator, RegExp pattern) {
    while (iterator.moveNext()) {
      if (pattern.hasMatch(iterator.current)) {
        return;
      }
    }
  }

  /// Writes the main project entry for the plugin with the given [guid] and
  /// [name].
  void _writePluginProjectEntry(String guid, String name, StringBuffer output) {
    output.write('''
Project("{$_kSolutionTypeGuidVcxproj}") = "$name", "Flutter\\ephemeral\\.plugin_symlinks\\$name\\windows\\plugin.vcxproj", "{$guid}"\r
\tProjectSection(ProjectDependencies) = postProject\r
\t\t{$_kFlutterBuildProjectGuid} = {$_kFlutterBuildProjectGuid}\r
\tEndProjectSection\r
EndProject\r
''');
  }

  /// Writes the main project entry for the Flutter Plugins solution folder.
  void _writePluginFolderProjectEntry(StringBuffer output) {
    const String folderName = 'Flutter Plugins';
    output.write('''
Project("{$_kSolutionTypeGuidFolder}") = "$folderName", "$folderName", "{$_kFlutterPluginSolutionFolderGuid}"\r
EndProject\r
''');
  }

  /// Writes a project dependencies section, depending on all the GUIDs in
  /// [dependencies].
  void _writeDependenciesSection(Iterable<String> dependencies, StringBuffer output) {
    output.writeln('ProjectSection(ProjectDependencies) = postProject\r');
    for (final String guid in dependencies) {
      _writeProjectDependency(guid, output);
    }
    output.writeln('EndProjectSection\r');
  }

  /// Returns the GUIDs of all the Flutter plugin projects in the given solution.
  Set<String> _findPreviousPluginGuids(String solutionContent) {
    // Find the plugin folder's known GUID in ProjectDependencies lines.
    // Each line in that section has the form:
    //   {project GUID} = {solution folder GUID}
    final RegExp pluginFolderChildrenPattern = RegExp(
        r'^\s*{([A-Fa-f0-9\-]*)}\s*=\s*{' + _kFlutterPluginSolutionFolderGuid + r'}\s*$',
        multiLine: true,
    );
    return pluginFolderChildrenPattern
        .allMatches(solutionContent)
        .map((Match match) => match.group(1)).toSet();
  }

  /// Returns a mapping of plugin project GUID to name for all the Windows plugins
  /// in [plugins].
  Map<String, String> _getWindowsPluginNamesByGuid(List<Plugin> plugins) {
    final Map<String, String> currentPluginInfo = <String, String>{};
    for (final Plugin plugin in plugins) {
      if (plugin.platforms.containsKey(_project.pluginConfigKey)) {
        final _PluginProjectInfo info = _PluginProjectInfo(plugin, fileSystem: _fileSystem);
        if (currentPluginInfo.containsKey(info.guid)) {
          throwToolExit('The plugins "${currentPluginInfo[info.guid]}" and "${info.name}" '
              'have the same ProjectGuid, which prevents them from being used together.\n\n'
              'Please contact the plugin authors to resolve this, and/or remove one of the '
              'plugins from your project.');
        }
        currentPluginInfo[info.guid] = info.name;
      }
    }
    return currentPluginInfo;
  }

  /// Walks a GlobalSection or ProjectSection, removing entries related to removed
  /// plugins and adding entries for new plugins at the end using
  /// [newEntryWriter], which takes the guid of the plugin to write entries for.
  ///
  /// The caller is responsible for printing the section start line, which should
  /// be [lineIterator.current] when this is called, and the section end line,
  /// which will be [lineIterator.current] on return.
  void _processSectionPluginReferences(
      Set<String> removedPlugins,
      Set<String> addedPlugins,
      Iterator<String> lineIterator,
      Function(String, StringBuffer) newEntryWriter,
      StringBuffer output,
  ) {
    // Extracts the guid of the project that a line refers to. Currently all
    // sections this function is used for start with "{project guid}", even though
    // the rest of the line varies by section, so the pattern can currently be
    // shared rather than parameterized.
    final RegExp entryPattern = RegExp(r'^\s*{([A-Fa-f0-9\-]*)}');
    final RegExp sectionEndPattern = RegExp(r'^\s*End\w*Section\s*$');
    while (lineIterator.moveNext()) {
      if (sectionEndPattern.hasMatch(lineIterator.current)) {
        // The end of the section; add entries for new plugins, then exit.
        for (final String guid in addedPlugins) {
          newEntryWriter(guid, output);
        }
        return;
      }
      // Otherwise it's the sectino body. Drop any lines associated with old
      // plugins, but pass everything else through as output.
      final Match entryMatch = entryPattern.firstMatch(lineIterator.current);
      if (entryMatch != null && removedPlugins.contains(entryMatch.group(1))) {
        continue;
      }
      output.writeln(lineIterator.current);
    }
  }

  /// Writes all the configuration entries for the plugin project with the given
  /// [guid].
  ///
  /// Should be called within the context of writing
  /// GlobalSection(ProjectConfigurationPlatforms).
  void _writePluginConfigurationEntries(String guid, StringBuffer output) {
    final List<String> configurations = <String>['Debug', 'Profile', 'Release'];
    final List<String> entryTypes = <String>['ActiveCfg', 'Build.0'];
    for (final String configuration in configurations) {
      for (final String entryType in entryTypes) {
        output.writeln('\t\t{$guid}.$configuration|x64.$entryType = $configuration|x64\r');
      }
    }
  }

  /// Writes the entries to nest the plugin projects with the given [guid] under
  /// the Flutter Plugins solution folder.
  ///
  /// Should be called within the context of writing
  /// GlobalSection(NestedProjects).
  void _writePluginNestingEntry(String guid, StringBuffer output) {
    output.writeln('\t\t{$guid} = {$_kFlutterPluginSolutionFolderGuid}\r');
  }

  /// Writes the entrie to make a project depend on another project with the
  /// given [guid].
  ///
  /// Should be called within the context of writing
  /// ProjectSection(ProjectDependencies).
  void _writeProjectDependency(String guid, StringBuffer output) {
    output.writeln('\t\t{$guid} = {$guid}\r');
  }
}
