// Copyright 2019 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 'dart:convert';

import 'package:cocoon_service/src/service/scheduler/policy.dart';
import 'package:github/github.dart';

import '../luci/buildbucket.dart';
import '../proto/internal/scheduler.pb.dart' as pb;

/// Wrapper class around [pb.Target] to support aggregate properties.
///
/// Changes here may also need to be upstreamed in:
///  * https://flutter.googlesource.com/infra/+/refs/heads/main/config/lib/ci_yaml/ci_yaml.star
class Target {
  Target({
    required this.value,
    required this.schedulerConfig,
    required this.slug,
  });

  /// Underlying [Target] this is based on.
  final pb.Target value;

  /// The [SchedulerConfig] [value] is from.
  ///
  /// This is passed for necessary lookups to platform level details.
  final pb.SchedulerConfig schedulerConfig;

  /// The [RepositorySlug] this [Target] is run for.
  final RepositorySlug slug;

  /// Target prefixes that indicate it will run on an ios device.
  static const List<String> iosPlatforms = <String>['mac_ios', 'mac_arm64_ios'];

  /// Dimension list defined in .ci.yaml.
  static List<String> dimensionList = <String>['os', 'device_os', 'device_type', 'mac_model', 'cores', 'cpu'];

  static String kIgnoreFlakiness = 'ignore_flakiness';

  /// Gets assembled dimensions for this [pb.Target].
  ///
  /// Swarming dimension doc: https://chromium.googlesource.com/infra/luci/luci-go/+/HEAD/lucicfg/doc/README.md#swarming.dimension
  ///
  /// Target dimensions are prioritized in:
  ///   1. [pb.Target.dimensions]
  ///   1. [pb.Target.properties]
  ///   2. [schedulerConfig.platformDimensions]
  List<RequestedDimension> getDimensions() {
    final Map<String, RequestedDimension> dimensionsMap = <String, RequestedDimension>{};

    final Map<String, Object> platformDimensions = _getPlatformDimensions();
    for (String key in platformDimensions.keys) {
      String value = platformDimensions[key].toString();
      dimensionsMap[key] = RequestedDimension(key: key, value: value);
    }

    final Map<String, Object> properties = getProperties();
    // TODO(xilaizhang): https://github.com/flutter/flutter/issues/103557
    // remove this logic after dimensions are supported in ci.yaml files
    for (String dimension in dimensionList) {
      if (properties.containsKey(dimension)) {
        String value = properties[dimension].toString();
        dimensionsMap[dimension] = RequestedDimension(key: dimension, value: value);
      }
    }

    final Map<String, Object> targetDimensions = _getTargetDimensions();
    for (String key in targetDimensions.keys) {
      String value = targetDimensions[key].toString();
      dimensionsMap[key] = RequestedDimension(key: key, value: value);
    }

    return dimensionsMap.values.toList();
  }

  /// [SchedulerPolicy] this target follows.
  ///
  /// Targets not triggered by Cocoon will not be triggered.
  ///
  /// All targets run with [BatchPolicy] to reduce queue time.
  SchedulerPolicy get schedulerPolicy {
    if (value.scheduler != pb.SchedulerSystem.cocoon) {
      return OmitPolicy();
    }

    return BatchPolicy();
  }

  /// Get the tags from the defined properties in the ci.
  ///
  /// Return an empty list if no tags are found.
  List<String> get tags {
    Map<String, Object> properties = getProperties();
    return (properties.containsKey('tags')) ? (properties['tags'] as List).map((e) => e as String).toList() : [];
  }

  String get getTestName {
    final List<String> words = value.name.split(' ');
    return words.length < 2 ? words[0] : words[1];
  }

  /// Gets the assembled properties for this [pb.Target].
  ///
  /// Target properties are prioritized in:
  ///   1. [schedulerConfig.platformProperties]
  ///   2. [pb.Target.properties]
  Map<String, Object> getProperties() {
    final Map<String, Object> platformProperties = _getPlatformProperties();
    final Map<String, Object> properties = _getTargetProperties();
    final Map<String, Object> mergedProperties = <String, Object>{}
      ..addAll(platformProperties)
      ..addAll(properties);

    final List<Dependency> targetDependencies = <Dependency>[];
    if (properties.containsKey('dependencies')) {
      final List<dynamic> rawDeps = properties['dependencies'] as List<dynamic>;
      final Iterable<Dependency> deps = rawDeps.map((dynamic rawDep) => Dependency.fromJson(rawDep as Object));
      targetDependencies.addAll(deps);
    }
    final List<Dependency> platformDependencies = <Dependency>[];
    if (platformProperties.containsKey('dependencies')) {
      final List<dynamic> rawDeps = platformProperties['dependencies'] as List<dynamic>;
      final Iterable<Dependency> deps = rawDeps.map((dynamic rawDep) => Dependency.fromJson(rawDep as Object));
      platformDependencies.addAll(deps);
    }
    // Lookup map to make merging [targetDependencies] and [platformDependencies] simpler.
    final Map<String, Dependency> mergedDependencies = <String, Dependency>{};
    for (Dependency dep in platformDependencies) {
      mergedDependencies[dep.name] = dep;
    }
    for (Dependency dep in targetDependencies) {
      mergedDependencies[dep.name] = dep;
    }
    mergedProperties['dependencies'] = mergedDependencies.values.map((Dependency dep) => dep.toJson()).toList();

    // xcode is a special property as there's different download policies if its in the devicelab.
    if (mergedProperties.containsKey('xcode')) {
      final Object xcodeVersion = <String, Object>{
        'sdk_version': mergedProperties['xcode']!,
      };

      if (iosPlatforms.contains(getPlatform())) {
        mergedProperties['\$flutter/devicelab_osx_sdk'] = xcodeVersion;
      } else {
        mergedProperties['\$flutter/osx_sdk'] = xcodeVersion;
      }
    }
    // runtime_versions is a special property
    if (mergedProperties.containsKey('runtime_versions')) {
      // add to existing property, or create new one
      final Object osxSdk = mergedProperties['\$flutter/osx_sdk'] ?? <String, Object>{};
      (osxSdk as Map)['runtime_versions'] = mergedProperties['runtime_versions']!;
      mergedProperties['\$flutter/osx_sdk'] = osxSdk;
    }

    mergedProperties['bringup'] = value.bringup;

    return mergedProperties;
  }

  Map<String, Object> _getTargetDimensions() {
    final Map<String, Object> dimensions = <String, Object>{};
    for (String key in value.dimensions.keys) {
      dimensions[key] = _parseProperty(key, value.dimensions[key]!);
    }

    return dimensions;
  }

  Map<String, Object> _getTargetProperties() {
    final Map<String, Object> properties = <String, Object>{};
    for (String key in value.properties.keys) {
      properties[key] = _parseProperty(key, value.properties[key]!);
    }

    return properties;
  }

  Map<String, Object> _getPlatformProperties() {
    if (!schedulerConfig.platformProperties.containsKey(getPlatform())) {
      return <String, Object>{};
    }

    final Map<String, String> platformProperties = schedulerConfig.platformProperties[getPlatform()]!.properties;
    final Map<String, Object> properties = <String, Object>{};
    for (String key in platformProperties.keys) {
      properties[key] = _parseProperty(key, platformProperties[key]!);
    }

    return properties;
  }

  Map<String, Object> _getPlatformDimensions() {
    if (!schedulerConfig.platformProperties.containsKey(getPlatform())) {
      return <String, Object>{};
    }

    final Map<String, String> platformDimensions = schedulerConfig.platformProperties[getPlatform()]!.dimensions;
    final Map<String, Object> dimensions = <String, Object>{};
    for (String key in platformDimensions.keys) {
      dimensions[key] = _parseProperty(key, platformDimensions[key]!);
    }

    return dimensions;
  }

  /// Converts property strings to their correct type.
  ///
  /// Changes made here should also be made to [_platform_properties] and [_properties] in:
  ///  * https://cs.opensource.google/flutter/infra/+/main:config/lib/ci_yaml/ci_yaml.star
  Object _parseProperty(String key, String value) {
    // Yaml will escape new lines unnecessarily for strings.
    final List<String> newLineIssues = <String>['android_sdk_license', 'android_sdk_preview_license'];
    if (value == 'true') {
      return true;
    } else if (value == 'false') {
      return false;
    } else if (value.startsWith('[')) {
      return jsonDecode(value) as Object;
    } else if (newLineIssues.contains(key)) {
      return value.replaceAll('\\n', '\n');
    } else if (int.tryParse(value) != null) {
      return int.parse(value);
    }

    return value;
  }

  /// Get the platform of this [Target].
  ///
  /// Platform is extracted as the first word in a target's name.
  String getPlatform() {
    return value.name.split(' ').first.toLowerCase();
  }

  /// Indicates whether this target should be scheduled via batches.
  ///
  /// DeviceLab targets are special as they run on a host + physical device, and there is limited
  /// capacity in the labs to run them. Their platforms contain one of `android`, `ios`, and `samsung`.
  ///
  /// Mac host only targets are scheduled via patches due to high queue time. This can be relieved
  /// when we have capacity support in Q4/2022.
  bool get shouldBatchSchedule {
    final String platform = getPlatform();
    return platform.contains('android') ||
        platform.contains('ios') ||
        platform.contains('samsung') ||
        platform == 'mac';
  }

  /// Get the associated LUCI bucket to run this [Target] in.
  String getBucket() {
    return value.bringup ? 'staging' : 'prod';
  }

  /// Returns value of ignore_flakiness property.
  ///
  /// Returns the value of ignore_flakiness property if
  /// it has been specified, else default returns false.
  bool getIgnoreFlakiness() {
    final Map<String, Object> properties = getProperties();
    if (properties.containsKey(kIgnoreFlakiness)) {
      return properties[kIgnoreFlakiness] as bool;
    }
    return false;
  }
}

/// Representation of a Flutter dependency.
///
/// See more:
///   * https://flutter.googlesource.com/recipes/+/refs/heads/main/recipe_modules/flutter_deps/api.py
class Dependency {
  Dependency(this.name, this.version);

  /// Constructor for converting from the flutter_deps format.
  factory Dependency.fromJson(Object json) {
    final Map<String, dynamic> map = json as Map<String, dynamic>;
    return Dependency(map['dependency']! as String, map['version'] as String?);
  }

  /// Human readable name of the dependency.
  final String name;

  /// CIPD tag to use.
  ///
  /// If null, will use the version set in the flutter_deps recipe_module.
  final String? version;

  Map<String, Object> toJson() {
    return <String, Object>{
      'dependency': name,
      if (version != null) 'version': version!,
    };
  }
}
