// 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/io.dart';
import '../base/user_messages.dart';
import '../base/version.dart';
import '../doctor.dart';

/// A combination of version description and parsed version number.
class _VersionInfo {
  /// Constructs a VersionInfo from a version description string.
  ///
  /// This should contain a version number. For example:
  ///     "clang version 9.0.1-6+build1"
  _VersionInfo(this.description) {
    final String versionString = RegExp(r'[0-9]+\.[0-9]+(?:\.[0-9]+)?').firstMatch(description).group(0);
    number = Version.parse(versionString);
  }

  // The full info string reported by the binary.
  String description;

  // The parsed Version.
  Version number;
}

/// A validator that checks for Clang and Make build dependencies.
class LinuxDoctorValidator extends DoctorValidator {
  LinuxDoctorValidator({
    @required ProcessManager processManager,
    @required UserMessages userMessages,
  }) : _processManager = processManager,
       _userMessages = userMessages,
       super('Linux toolchain - develop for Linux desktop');

  final ProcessManager _processManager;
  final UserMessages _userMessages;

  static const String kClangBinary = 'clang++';
  static const String kCmakeBinary = 'cmake';
  static const String kNinjaBinary = 'ninja';
  static const String kPkgConfigBinary = 'pkg-config';

  final Map<String, Version> _requiredBinaryVersions = <String, Version>{
    kClangBinary: Version(3, 4, 0),
    kCmakeBinary: Version(3, 10, 0),
    kNinjaBinary: Version(1, 8, 0),
    kPkgConfigBinary: Version(0, 29, 0),
  };

  final List<String> _requiredGtkLibraries = <String>[
    'gtk+-3.0',
    'glib-2.0',
    'gio-2.0',
  ];

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

    final Map<String, _VersionInfo> installedVersions = <String, _VersionInfo>{
      // Sort the check to make the call order predictable for unit tests.
      for (String binary in _requiredBinaryVersions.keys.toList()..sort())
          binary: await _getBinaryVersion(binary)
    };

    // Determine overall validation level.
    if (installedVersions.values.contains(null)) {
      validationType = ValidationType.missing;
    } else if (installedVersions.keys.any((String binary) =>
          installedVersions[binary].number < _requiredBinaryVersions[binary])) {
      validationType = ValidationType.partial;
    }

    // Message for Clang.
    {
      final _VersionInfo version = installedVersions[kClangBinary];
      if (version == null) {
        messages.add(ValidationMessage.error(_userMessages.clangMissing));
      } else {
        messages.add(ValidationMessage(version.description));
        final Version requiredVersion = _requiredBinaryVersions[kClangBinary];
        if (version.number < requiredVersion) {
          messages.add(ValidationMessage.error(_userMessages.clangTooOld(requiredVersion.toString())));
        }
      }
    }

    // Message for CMake.
    {
      final _VersionInfo version = installedVersions[kCmakeBinary];
      if (version == null) {
        messages.add(ValidationMessage.error(_userMessages.cmakeMissing));
      } else {
        messages.add(ValidationMessage(version.description));
        final Version requiredVersion = _requiredBinaryVersions[kCmakeBinary];
        if (version.number < requiredVersion) {
          messages.add(ValidationMessage.error(_userMessages.cmakeTooOld(requiredVersion.toString())));
        }
      }
    }

    // Message for ninja.
    {
      final _VersionInfo version = installedVersions[kNinjaBinary];
      if (version == null) {
        messages.add(ValidationMessage.error(_userMessages.ninjaMissing));
      } else {
        // The full version description is just the number, so add context.
        messages.add(ValidationMessage(_userMessages.ninjaVersion(version.description)));
        final Version requiredVersion = _requiredBinaryVersions[kNinjaBinary];
        if (version.number < requiredVersion) {
          messages.add(ValidationMessage.error(_userMessages.ninjaTooOld(requiredVersion.toString())));
        }
      }
    }

    // Message for pkg-config.
    {
      final _VersionInfo version = installedVersions[kPkgConfigBinary];
      if (version == null) {
        messages.add(ValidationMessage.error(_userMessages.pkgConfigMissing));
      } else {
        // The full version description is just the number, so add context.
        messages.add(ValidationMessage(_userMessages.pkgConfigVersion(version.description)));
        final Version requiredVersion = _requiredBinaryVersions[kPkgConfigBinary];
        if (version.number < requiredVersion) {
          messages.add(ValidationMessage.error(_userMessages.pkgConfigTooOld(requiredVersion.toString())));
        }
      }
    }

    // Messages for libraries.
    {
      bool libraryMissing = false;
      for (final String library in _requiredGtkLibraries) {
        if (!await _libraryIsPresent(library)) {
          libraryMissing = true;
          break;
        }
      }
      if (libraryMissing) {
        validationType = ValidationType.missing;
        messages.add(ValidationMessage.error(_userMessages.gtkLibrariesMissing));
      }
    }
    if (!await _libraryIsPresent('blkid')) {
      validationType = ValidationType.missing;
      messages.add(ValidationMessage.error(_userMessages.blkidLibraryMissing));
    }

    return ValidationResult(validationType, messages);
  }

  /// Returns the installed version of [binary], or null if it's not installed.
  ///
  /// Requires tha [binary] take a '--version' flag, and print a version of the
  /// form x.y.z somewhere on the first line of output.
  Future<_VersionInfo> _getBinaryVersion(String binary) async {
    ProcessResult result;
    try {
      result = await _processManager.run(<String>[
        binary,
        '--version',
      ]);
    } on ArgumentError {
      // ignore error.
    }
    if (result == null || result.exitCode != 0) {
      return null;
    }
    final String firstLine = (result.stdout as String).split('\n').first.trim();
    return _VersionInfo(firstLine);
  }

  /// Checks that [library] is available via pkg-config.
  Future<bool> _libraryIsPresent(String library) async {
    ProcessResult result;
    try {
      result = await _processManager.run(<String>[
        'pkg-config',
        '--exists',
        library,
      ]);
    } on ArgumentError {
      // ignore error.
    }
    return (result?.exitCode ?? 1) == 0;
  }
}
