///|
pub struct QualityProfile {
  name : String
  max_errors : Int
  max_warnings : Int
  min_occupancy : Double
  max_duration : Int
  require_tags : Bool
} derive(Debug, Eq, ToJson, FromJson)

///|
pub fn QualityProfile::accepts(
  self : QualityProfile,
  report : QualityReport,
) -> Bool {
  report.errors <= self.max_errors &&
  report.warnings <= self.max_warnings &&
  report.occupancy >= self.min_occupancy &&
  report.total_duration <= self.max_duration &&
  (!self.require_tags || report.animation_count > 0)
}

///|
pub fn QualityProfile::to_json_string(
  self : QualityProfile,
  indent? : Int = 2,
) -> String {
  ToJson::to_json(self).stringify(indent~)
}

///|
pub fn quality_profiles() -> Array[QualityProfile] {
  [
    {
      name: "development",
      max_errors: 0,
      max_warnings: 8,
      min_occupancy: 0.20,
      max_duration: 5000,
      require_tags: false,
    },
    {
      name: "release",
      max_errors: 0,
      max_warnings: 2,
      min_occupancy: 0.45,
      max_duration: 3000,
      require_tags: true,
    },
    {
      name: "mobile-release",
      max_errors: 0,
      max_warnings: 1,
      min_occupancy: 0.55,
      max_duration: 2000,
      require_tags: true,
    },
    {
      name: "asset-library",
      max_errors: 0,
      max_warnings: 4,
      min_occupancy: 0.35,
      max_duration: 4000,
      require_tags: true,
    },
    {
      name: "strict-ci",
      max_errors: 0,
      max_warnings: 0,
      min_occupancy: 0.60,
      max_duration: 1500,
      require_tags: true,
    },
  ]
}

///|
pub fn quality_profile_named(name : String) -> QualityProfile? {
  match quality_profiles().search_by(fn(profile) { profile.name == name }) {
    Some(index) => Some(quality_profiles()[index])
    None => None
  }
}

///|
pub fn passing_quality_profiles(
  report : QualityReport,
) -> Array[QualityProfile] {
  quality_profiles().filter(fn(profile) { profile.accepts(report) })
}

///|
pub fn quality_profile_count() -> Int {
  quality_profiles().length()
}