// 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/async_guard.dart';
import 'base/terminal.dart';
import 'globals.dart' as globals;

class ValidatorTask {
  ValidatorTask(this.validator, this.result);
  final DoctorValidator validator;
  final Future<ValidationResult> result;
}

/// A series of tools and required install steps for a target platform (iOS or Android).
abstract class Workflow {
  const Workflow();

  /// Whether the workflow applies to this platform (as in, should we ever try and use it).
  bool get appliesToHostPlatform;

  /// Are we functional enough to list devices?
  bool get canListDevices;

  /// Could this thing launch *something*? It may still have minor issues.
  bool get canLaunchDevices;

  /// Are we functional enough to list emulators?
  bool get canListEmulators;
}

enum ValidationType {
  crash,
  missing,
  partial,
  notAvailable,
  success,
}

enum ValidationMessageType {
  error,
  hint,
  information,
}

abstract class DoctorValidator {
  const DoctorValidator(this.title);

  /// This is displayed in the CLI.
  final String title;

  String get slowWarning => 'This is taking an unexpectedly long time...';

  static const Duration _slowWarningDuration = Duration(seconds: 10);

  /// Duration before the spinner should display [slowWarning].
  Duration get slowWarningDuration => _slowWarningDuration;

  Future<ValidationResult> validate();
}

/// A validator that runs other [DoctorValidator]s and combines their output
/// into a single [ValidationResult]. It uses the title of the first validator
/// passed to the constructor and reports the statusInfo of the first validator
/// that provides one. Other titles and statusInfo strings are discarded.
class GroupedValidator extends DoctorValidator {
  GroupedValidator(this.subValidators) : super(subValidators[0].title);

  final List<DoctorValidator> subValidators;

  List<ValidationResult> _subResults = <ValidationResult>[];

  /// Sub-validator results.
  ///
  /// To avoid losing information when results are merged, the sub-results are
  /// cached on this field when they are available. The results are in the same
  /// order as the sub-validator list.
  List<ValidationResult> get subResults => _subResults;

  @override
  String get slowWarning => _currentSlowWarning;
  String _currentSlowWarning = 'Initializing...';

  @override
  Future<ValidationResult> validate() async {
    final List<ValidatorTask> tasks = <ValidatorTask>[
      for (final DoctorValidator validator in subValidators)
        ValidatorTask(
          validator,
          asyncGuard<ValidationResult>(() => validator.validate()),
        ),
    ];

    final List<ValidationResult> results = <ValidationResult>[];
    for (final ValidatorTask subValidator in tasks) {
      _currentSlowWarning = subValidator.validator.slowWarning;
      try {
        results.add(await subValidator.result);
      } on Exception catch (exception, stackTrace) {
        results.add(ValidationResult.crash(exception, stackTrace));
      }
    }
    _currentSlowWarning = 'Merging results...';
    return _mergeValidationResults(results);
  }

  ValidationResult _mergeValidationResults(List<ValidationResult> results) {
    assert(results.isNotEmpty, 'Validation results should not be empty');
    _subResults = results;
    ValidationType mergedType = results[0].type;
    final List<ValidationMessage> mergedMessages = <ValidationMessage>[];
    String? statusInfo;

    for (final ValidationResult result in results) {
      statusInfo ??= result.statusInfo;
      switch (result.type) {
        case ValidationType.success:
          if (mergedType == ValidationType.missing) {
            mergedType = ValidationType.partial;
          }
          break;
        case ValidationType.notAvailable:
        case ValidationType.partial:
          mergedType = ValidationType.partial;
          break;
        case ValidationType.crash:
        case ValidationType.missing:
          if (mergedType == ValidationType.success) {
            mergedType = ValidationType.partial;
          }
          break;
      }
      mergedMessages.addAll(result.messages);
    }

    return ValidationResult(mergedType, mergedMessages,
        statusInfo: statusInfo);
  }
}

@immutable
class ValidationResult {
  /// [ValidationResult.type] should only equal [ValidationResult.success]
  /// if no [messages] are hints or errors.
  const ValidationResult(this.type, this.messages, { this.statusInfo });

  factory ValidationResult.crash(Object error, [StackTrace? stackTrace]) {
    return ValidationResult(ValidationType.crash, <ValidationMessage>[
      const ValidationMessage.error(
          'Due to an error, the doctor check did not complete. '
          'If the error message below is not helpful, '
          'please let us know about this issue at https://github.com/flutter/flutter/issues.'),
      ValidationMessage.error('$error'),
      if (stackTrace != null)
          // Stacktrace is informational. Printed in verbose mode only.
          ValidationMessage('$stackTrace'),
    ], statusInfo: 'the doctor check crashed');
  }

  final ValidationType type;
  // A short message about the status.
  final String? statusInfo;
  final List<ValidationMessage> messages;

  String get leadingBox {
    switch (type) {
      case ValidationType.crash:
        return '[☠]';
      case ValidationType.missing:
        return '[✗]';
      case ValidationType.success:
        return '[✓]';
      case ValidationType.notAvailable:
      case ValidationType.partial:
        return '[!]';
    }
  }

  String get coloredLeadingBox {
    switch (type) {
      case ValidationType.crash:
        return globals.terminal.color(leadingBox, TerminalColor.red);
      case ValidationType.missing:
        return globals.terminal.color(leadingBox, TerminalColor.red);
      case ValidationType.success:
        return globals.terminal.color(leadingBox, TerminalColor.green);
      case ValidationType.notAvailable:
      case ValidationType.partial:
        return globals.terminal.color(leadingBox, TerminalColor.yellow);
    }
  }

  /// The string representation of the type.
  String get typeStr {
    switch (type) {
      case ValidationType.crash:
        return 'crash';
      case ValidationType.missing:
        return 'missing';
      case ValidationType.success:
        return 'installed';
      case ValidationType.notAvailable:
        return 'notAvailable';
      case ValidationType.partial:
        return 'partial';
    }
  }
}

/// A status line for the flutter doctor validation to display.
///
/// The [message] is required and represents either an informational statement
/// about the particular doctor validation that passed, or more context
/// on the cause and/or solution to the validation failure.
@immutable
class ValidationMessage {
  /// Create a validation message with information for a passing validator.
  ///
  /// By default this is not displayed unless the doctor is run in
  /// verbose mode.
  ///
  /// The [contextUrl] may be supplied to link to external resources. This
  /// is displayed after the informative message in verbose modes.
  const ValidationMessage(this.message, { this.contextUrl, String? piiStrippedMessage })
      : type = ValidationMessageType.information, piiStrippedMessage = piiStrippedMessage ?? message;

  /// Create a validation message with information for a failing validator.
  const ValidationMessage.error(this.message, { String? piiStrippedMessage })
    : type = ValidationMessageType.error,
      piiStrippedMessage = piiStrippedMessage ?? message,
      contextUrl = null;

  /// Create a validation message with information for a partially failing
  /// validator.
  const ValidationMessage.hint(this.message, { String? piiStrippedMessage })
    : type = ValidationMessageType.hint,
      piiStrippedMessage = piiStrippedMessage ?? message,
      contextUrl = null;

  final ValidationMessageType type;
  final String? contextUrl;
  final String message;
  /// Optional message with PII stripped, to show instead of [message].
  final String piiStrippedMessage;

  bool get isError => type == ValidationMessageType.error;

  bool get isHint => type == ValidationMessageType.hint;

  bool get isInformation => type == ValidationMessageType.information;

  String get indicator {
    switch (type) {
      case ValidationMessageType.error:
        return '✗';
      case ValidationMessageType.hint:
        return '!';
      case ValidationMessageType.information:
        return '•';
    }
  }

  String get coloredIndicator {
    switch (type) {
      case ValidationMessageType.error:
        return globals.terminal.color(indicator, TerminalColor.red);
      case ValidationMessageType.hint:
        return globals.terminal.color(indicator, TerminalColor.yellow);
      case ValidationMessageType.information:
        return globals.terminal.color(indicator, TerminalColor.green);
    }
  }

  @override
  String toString() => message;

  @override
  bool operator ==(Object other) {
    return other is ValidationMessage
        && other.message == message
        && other.type == type
        && other.contextUrl == contextUrl;
  }

  @override
  int get hashCode => Object.hash(type, message, contextUrl);
}

class NoIdeValidator extends DoctorValidator {
  NoIdeValidator() : super('Flutter IDE Support');

  @override
  Future<ValidationResult> validate() async {
    return ValidationResult(
      // Info hint to user they do not have a supported IDE installed
      ValidationType.notAvailable,
      globals.userMessages.noIdeInstallationInfo.map((String ideInfo) => ValidationMessage(ideInfo)).toList(),
      statusInfo: globals.userMessages.noIdeStatusInfo,
    );
  }
}

class ValidatorWithResult extends DoctorValidator {
  ValidatorWithResult(super.title, this.result);

  final ValidationResult result;

  @override
  Future<ValidationResult> validate() async => result;
}
