// 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();
  }

  /// 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!,
    };
  }
}
