// 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 'package:process/process.dart';

import '../base/file_system.dart';
import '../base/io.dart';
import '../base/platform.dart';
import '../base/user_messages.dart' hide userMessages;
import '../base/version.dart';
import '../convert.dart';
import '../doctor_validator.dart';
import '../ios/plist_parser.dart';
import 'intellij.dart';

const String _ultimateEditionTitle = 'IntelliJ IDEA Ultimate Edition';
const String _ultimateEditionId = 'IntelliJIdea';
const String _communityEditionTitle = 'IntelliJ IDEA Community Edition';
const String _communityEditionId = 'IdeaIC';

/// A doctor validator for both Intellij and Android Studio.
abstract class IntelliJValidator extends DoctorValidator {
  IntelliJValidator(String title, this.installPath, {
    required FileSystem fileSystem,
    required UserMessages userMessages,
  }) : _fileSystem = fileSystem,
       _userMessages = userMessages,
       super(title);

  final String installPath;
  final FileSystem _fileSystem;
  final UserMessages _userMessages;

  String get version;

  String? get pluginsPath;

  static const Map<String, String> _idToTitle = <String, String>{
    _ultimateEditionId: _ultimateEditionTitle,
    _communityEditionId: _communityEditionTitle,
  };

  static final Version kMinIdeaVersion = Version(2017, 1, 0);

  /// Create a [DoctorValidator] for each installation of Intellij.
  ///
  /// On platforms other than macOS, Linux, and Windows this returns an
  /// empty list.
  static Iterable<DoctorValidator> installedValidators({
    required FileSystem fileSystem,
    required Platform platform,
    required UserMessages userMessages,
    required PlistParser plistParser,
    required ProcessManager processManager,
  }) {
    final FileSystemUtils fileSystemUtils = FileSystemUtils(fileSystem: fileSystem, platform: platform);
    if (platform.isWindows) {
      return IntelliJValidatorOnWindows.installed(
        fileSystem: fileSystem,
        fileSystemUtils: fileSystemUtils,
        platform: platform,
        userMessages: userMessages,
      );
    }
    if (platform.isLinux) {
      return IntelliJValidatorOnLinux.installed(
        fileSystem: fileSystem,
        fileSystemUtils: fileSystemUtils,
        userMessages: userMessages,
      );
    }
    if (platform.isMacOS) {
      return IntelliJValidatorOnMac.installed(
        fileSystem: fileSystem,
        fileSystemUtils: fileSystemUtils,
        userMessages: userMessages,
        plistParser: plistParser,
        processManager: processManager,
      );
    }
    return <DoctorValidator>[];
  }

  @override
  Future<ValidationResult> validate() async {
    final List<ValidationMessage> messages = <ValidationMessage>[];

    if (pluginsPath == null) {
      messages.add(const ValidationMessage.error('Invalid IntelliJ version number.'));
    } else {
      messages.add(ValidationMessage(_userMessages.intellijLocation(installPath)));

      final IntelliJPlugins plugins = IntelliJPlugins(pluginsPath!, fileSystem: _fileSystem);
      plugins.validatePackage(
        messages,
        <String>['flutter-intellij', 'flutter-intellij.jar'],
        'Flutter',
        IntelliJPlugins.kIntellijFlutterPluginUrl,
        minVersion: IntelliJPlugins.kMinFlutterPluginVersion,
      );
      plugins.validatePackage(
        messages,
        <String>['Dart'],
        'Dart',
        IntelliJPlugins.kIntellijDartPluginUrl,
      );

      if (_hasIssues(messages)) {
        messages.add(ValidationMessage(_userMessages.intellijPluginInfo));
      }

      _validateIntelliJVersion(messages, kMinIdeaVersion);
    }

    return ValidationResult(
      _hasIssues(messages) ? ValidationType.partial : ValidationType.installed,
      messages,
      statusInfo: _userMessages.intellijStatusInfo(version),
    );
  }

  bool _hasIssues(List<ValidationMessage> messages) {
    return messages.any((ValidationMessage message) => message.isError);
  }

  void _validateIntelliJVersion(List<ValidationMessage> messages, Version minVersion) {
    // Ignore unknown versions.
    if (minVersion == Version.unknown) {
      return;
    }

    final Version? installedVersion = Version.parse(version);
    if (installedVersion == null) {
      return;
    }

    if (installedVersion < minVersion) {
      messages.add(ValidationMessage.error(_userMessages.intellijMinimumVersion(minVersion.toString())));
    }
  }
}

/// A windows specific implementation of the intellij validator.
class IntelliJValidatorOnWindows extends IntelliJValidator {
  IntelliJValidatorOnWindows(String title, this.version, String installPath, this.pluginsPath, {
    required FileSystem fileSystem,
    required UserMessages userMessages,
  }) : super(title, installPath, fileSystem: fileSystem, userMessages: userMessages);

  @override
  final String version;

  @override
  final String pluginsPath;

  static Iterable<DoctorValidator> installed({
    required FileSystem fileSystem,
    required FileSystemUtils fileSystemUtils,
    required Platform platform,
    required UserMessages userMessages,
  }) {
    final List<DoctorValidator> validators = <DoctorValidator>[];
    if (fileSystemUtils.homeDirPath == null) {
      return validators;
    }

    void addValidator(String title, String version, String installPath, String pluginsPath) {
      final IntelliJValidatorOnWindows validator = IntelliJValidatorOnWindows(
        title,
        version,
        installPath,
        pluginsPath,
        fileSystem: fileSystem,
        userMessages: userMessages,
      );
      for (int index = 0; index < validators.length; index += 1) {
        final DoctorValidator other = validators[index];
        if (other is IntelliJValidatorOnWindows && validator.installPath == other.installPath) {
          if (validator.version.compareTo(other.version) > 0) {
            validators[index] = validator;
          }
          return;
        }
      }
      validators.add(validator);
    }

    // before IntelliJ 2019
    final Directory homeDir = fileSystem.directory(fileSystemUtils.homeDirPath);
    for (final Directory dir in homeDir.listSync().whereType<Directory>()) {
      final String name = fileSystem.path.basename(dir.path);
      IntelliJValidator._idToTitle.forEach((String id, String title) {
        if (name.startsWith('.$id')) {
          final String version = name.substring(id.length + 1);
          String? installPath;
          try {
            installPath = fileSystem.file(fileSystem.path.join(dir.path, 'system', '.home')).readAsStringSync();
          } on FileSystemException {
            // ignored
          }
          if (installPath != null && fileSystem.isDirectorySync(installPath)) {
            final String pluginsPath = fileSystem.path.join(dir.path, 'config', 'plugins');
            addValidator(title, version, installPath, pluginsPath);
          }
        }
      });
    }

    // after IntelliJ 2020
    if (!platform.environment.containsKey('LOCALAPPDATA')) {
      return validators;
    }
    final Directory cacheDir = fileSystem.directory(fileSystem.path.join(platform.environment['LOCALAPPDATA']!, 'JetBrains'));
    if (!cacheDir.existsSync()) {
      return validators;
    }
    for (final Directory dir in cacheDir.listSync().whereType<Directory>()) {
      final String name = fileSystem.path.basename(dir.path);
      IntelliJValidator._idToTitle.forEach((String id, String title) {
        if (name.startsWith(id)) {
          final String version = name.substring(id.length);
          String? installPath;
          try {
            installPath = fileSystem.file(fileSystem.path.join(dir.path, '.home')).readAsStringSync();
          } on FileSystemException {
            // ignored
          }
          if (installPath != null && fileSystem.isDirectorySync(installPath)) {
            String pluginsPath;
            if (fileSystem.isDirectorySync(installPath + '.plugins')) {
              // IntelliJ 2020.3
              pluginsPath = installPath + '.plugins';
              addValidator(title, version, installPath, pluginsPath);
            } else if (platform.environment.containsKey('APPDATA')) {
              final String pluginsPathInAppData = fileSystem.path.join(
                  platform.environment['APPDATA']!, 'JetBrains', name, 'plugins');
              if (fileSystem.isDirectorySync(pluginsPathInAppData)) {
                // IntelliJ 2020.1 ~ 2020.2
                pluginsPath = pluginsPathInAppData;
                addValidator(title, version, installPath, pluginsPath);
              }
            }
          }
        }
      });
    }
    return validators;
  }
}

/// A linux specific implementation of the intellij validator.
class IntelliJValidatorOnLinux extends IntelliJValidator {
  IntelliJValidatorOnLinux(String title, this.version, String installPath, this.pluginsPath, {
    required FileSystem fileSystem,
    required UserMessages userMessages,
  }) : super(title, installPath, fileSystem: fileSystem, userMessages: userMessages);

  @override
  final String version;

  @override
  final String pluginsPath;

  static Iterable<DoctorValidator> installed({
    required FileSystem fileSystem,
    required FileSystemUtils fileSystemUtils,
    required UserMessages userMessages,
  }) {
    final List<DoctorValidator> validators = <DoctorValidator>[];
    final String? homeDirPath = fileSystemUtils.homeDirPath;
    if (homeDirPath == null) {
      return validators;
    }

    void addValidator(String title, String version, String installPath, String pluginsPath) {
      final IntelliJValidatorOnLinux validator = IntelliJValidatorOnLinux(
        title,
        version,
        installPath,
        pluginsPath,
        fileSystem: fileSystem,
        userMessages: userMessages,
      );
      for (int index = 0; index < validators.length; index += 1) {
        final DoctorValidator other = validators[index];
        if (other is IntelliJValidatorOnLinux && validator.installPath == other.installPath) {
          if (validator.version.compareTo(other.version) > 0) {
            validators[index] = validator;
          }
          return;
        }
      }
      validators.add(validator);
    }

    // before IntelliJ 2019
    final Directory homeDir = fileSystem.directory(homeDirPath);
    for (final Directory dir in homeDir.listSync().whereType<Directory>()) {
      final String name = fileSystem.path.basename(dir.path);
      IntelliJValidator._idToTitle.forEach((String id, String title) {
        if (name.startsWith('.$id')) {
          final String version = name.substring(id.length + 1);
          String? installPath;
          try {
            installPath = fileSystem.file(fileSystem.path.join(dir.path, 'system', '.home')).readAsStringSync();
          } on FileSystemException {
            // ignored
          }
          if (installPath != null && fileSystem.isDirectorySync(installPath)) {
            final String pluginsPath = fileSystem.path.join(dir.path, 'config', 'plugins');
            addValidator(title, version, installPath, pluginsPath);
          }
        }
      });
    }
    // after IntelliJ 2020 ~
    final Directory cacheDir = fileSystem.directory(fileSystem.path.join(homeDirPath, '.cache', 'JetBrains'));
    if (!cacheDir.existsSync()) {
      return validators;
    }
    for (final Directory dir in cacheDir.listSync().whereType<Directory>()) {
      final String name = fileSystem.path.basename(dir.path);
      IntelliJValidator._idToTitle.forEach((String id, String title) {
        if (name.startsWith(id)) {
          final String version = name.substring(id.length);
          String? installPath;
          try {
            installPath = fileSystem.file(fileSystem.path.join(dir.path, '.home')).readAsStringSync();
          } on FileSystemException {
            // ignored
          }
          if (installPath != null && fileSystem.isDirectorySync(installPath)) {
            final String pluginsPathInUserHomeDir = fileSystem.path.join(
                homeDirPath,
                '.local',
                'share',
                'JetBrains',
                name);
            if (installPath.contains(fileSystem.path.join('JetBrains','Toolbox','apps'))) {
              // via JetBrains ToolBox app
              final String pluginsPathInInstallDir = installPath + '.plugins';
              if (fileSystem.isDirectorySync(pluginsPathInUserHomeDir)) {
                // after 2020.2.x
                final String pluginsPath = pluginsPathInUserHomeDir;
                addValidator(title, version, installPath, pluginsPath);
              } else if (fileSystem.isDirectorySync(pluginsPathInInstallDir)) {
                // only 2020.1.X
                final String pluginsPath = pluginsPathInInstallDir;
                addValidator(title, version, installPath, pluginsPath);
              }
            } else {
              // via tar.gz
              final String pluginsPath = pluginsPathInUserHomeDir;
              addValidator(title, version, installPath, pluginsPath);
            }
          }
        }
      });
    }
    return validators;
  }
}

/// A macOS specific implementation of the intellij validator.
class IntelliJValidatorOnMac extends IntelliJValidator {
  IntelliJValidatorOnMac(String title, this.id, String installPath, {
    required FileSystem fileSystem,
    required UserMessages userMessages,
    required PlistParser plistParser,
    required String? homeDirPath,
  }) : _plistParser = plistParser,
       _homeDirPath = homeDirPath,
       super(title, installPath, fileSystem: fileSystem, userMessages: userMessages);

  final String id;
  final PlistParser _plistParser;
  final String? _homeDirPath;

  static const Map<String, String> _dirNameToId = <String, String>{
    'IntelliJ IDEA.app': _ultimateEditionId,
    'IntelliJ IDEA Ultimate.app': _ultimateEditionId,
    'IntelliJ IDEA CE.app': _communityEditionId,
  };

  static Iterable<DoctorValidator> installed({
    required FileSystem fileSystem,
    required FileSystemUtils fileSystemUtils,
    required UserMessages userMessages,
    required PlistParser plistParser,
    required ProcessManager processManager,
  }) {
    final List<DoctorValidator> validators = <DoctorValidator>[];
    final String? homeDirPath = fileSystemUtils.homeDirPath;
    final List<String> installPaths = <String>[
      '/Applications',
      if (homeDirPath != null)
        fileSystem.path.join(homeDirPath, 'Applications'),
    ];

    void checkForIntelliJ(Directory dir) {
      final String name = fileSystem.path.basename(dir.path);
      _dirNameToId.forEach((String dirName, String id) {
        if (name == dirName) {
          assert(IntelliJValidator._idToTitle.containsKey(id));
          final String title = IntelliJValidator._idToTitle[id]!;
          validators.add(IntelliJValidatorOnMac(
            title,
            id,
            dir.path,
            fileSystem: fileSystem,
            userMessages: userMessages,
            plistParser: plistParser,
            homeDirPath: homeDirPath,
          ));
        }
      });
    }

    try {
      final Iterable<Directory> installDirs = installPaths
        .map(fileSystem.directory)
        .map<List<FileSystemEntity>>((Directory dir) => dir.existsSync() ? dir.listSync() : <FileSystemEntity>[])
        .expand<FileSystemEntity>((List<FileSystemEntity> mappedDirs) => mappedDirs)
        .whereType<Directory>();
      for (final Directory dir in installDirs) {
        checkForIntelliJ(dir);
        if (!dir.path.endsWith('.app')) {
          for (final FileSystemEntity subdirectory in dir.listSync()) {
            if (subdirectory is Directory) {
              checkForIntelliJ(subdirectory);
            }
          }
        }
      }

      // Query Spotlight for unexpected installation locations.
      String ceSpotlightResult = '';
      String ultimateSpotlightResult = '';
      try {
        final ProcessResult ceQueryResult = processManager.runSync(<String>[
          'mdfind',
          'kMDItemCFBundleIdentifier="com.jetbrains.intellij.ce"',
        ]);
        ceSpotlightResult = ceQueryResult.stdout as String;
        final ProcessResult ultimateQueryResult = processManager.runSync(<String>[
          'mdfind',
          'kMDItemCFBundleIdentifier="com.jetbrains.intellij*"',
        ]);
        ultimateSpotlightResult = ultimateQueryResult.stdout as String;
      } on ProcessException {
        // The Spotlight query is a nice-to-have, continue checking known installation locations.
      }

      for (final String installPath in LineSplitter.split(ceSpotlightResult)) {
        if (!validators.whereType<IntelliJValidatorOnMac>().any((IntelliJValidatorOnMac e) => e.installPath == installPath)) {
          validators.add(IntelliJValidatorOnMac(
            _communityEditionTitle,
            _communityEditionId,
            installPath,
            fileSystem: fileSystem,
            userMessages: userMessages,
            plistParser: plistParser,
            homeDirPath: homeDirPath,
          ));
        }
      }

      for (final String installPath in LineSplitter.split(ultimateSpotlightResult)) {
        if (!validators.whereType<IntelliJValidatorOnMac>().any((IntelliJValidatorOnMac e) => e.installPath == installPath)) {
          validators.add(IntelliJValidatorOnMac(
            _ultimateEditionTitle,
            _ultimateEditionId,
            installPath,
            fileSystem: fileSystem,
            userMessages: userMessages,
            plistParser: plistParser,
            homeDirPath: homeDirPath,
          ));
        }
      }
    } on FileSystemException catch (e) {
      validators.add(ValidatorWithResult(
          userMessages.intellijMacUnknownResult,
          ValidationResult(ValidationType.missing, <ValidationMessage>[
            ValidationMessage.error(e.message),
          ]),
      ));
    }
    return validators;
  }

  @visibleForTesting
  String get plistFile {
    _plistFile ??= _fileSystem.path.join(installPath, 'Contents', 'Info.plist');
    return _plistFile!;
  }
  String? _plistFile;

  @override
  String get version {
    return _version ??= _plistParser.getValueFromFile(
        plistFile,
        PlistParser.kCFBundleShortVersionStringKey,
      ) ?? 'unknown';
  }
  String? _version;

  @override
  String? get pluginsPath {
    if (_pluginsPath != null) {
      return _pluginsPath!;
    }

    final String? altLocation = _plistParser
      .getValueFromFile(plistFile, 'JetBrainsToolboxApp');

    if (altLocation != null) {
      _pluginsPath = altLocation + '.plugins';
      return _pluginsPath!;
    }

    final List<String> split = version.split('.');
    if (split.length < 2) {
      return null;
    }
    final String major = split[0];
    final String minor = split[1];

    final String? homeDirPath = _homeDirPath;
    if (homeDirPath != null) {
      String pluginsPath = _fileSystem.path.join(
        homeDirPath,
        'Library',
        'Application Support',
        'JetBrains',
        '$id$major.$minor',
        'plugins',
      );
      // Fallback to legacy location from < 2020.
      if (!_fileSystem.isDirectorySync(pluginsPath)) {
        pluginsPath = _fileSystem.path.join(
          homeDirPath,
          'Library',
          'Application Support',
          '$id$major.$minor',
        );
      }
      _pluginsPath = pluginsPath;
    }

    return _pluginsPath;
  }
  String? _pluginsPath;
}
