///|
pub fn analyze_license(text : String) -> LicenseFacts {
  let lower = ascii_lower(text)
  let family = detect_license_family(lower)
  let spdx = license_spdx(family)
  let osi = license_is_osi(family)
  license_facts(
    family,
    spdx,
    osi,
    contains(lower, "copyright"),
    contains(lower, "permission is hereby granted") ||
    contains(lower, "licensed under the apache license"),
    contains(lower, "without warranty") || contains(lower, "as is"),
    contains(lower, "patent") || family == Apache2,
  )
}

///|
pub fn LicenseFacts::summary(self : LicenseFacts) -> String {
  "license=\{self.spdx_id}, osi=\{bool_text(self.osi_approved)}, copyright=\{bool_text(self.has_copyright)}"
}

///|
pub fn LicenseFacts::completeness_score(self : LicenseFacts) -> Int {
  let mut score = 0
  if self.osi_approved {
    score += 35
  }
  if self.has_copyright {
    score += 20
  }
  if self.has_permission_grant {
    score += 20
  }
  if self.has_warranty_disclaimer {
    score += 20
  }
  if self.has_patent_grant {
    score += 5
  }
  score
}

///|
pub fn LicenseFacts::is_publishable(self : LicenseFacts) -> Bool {
  self.osi_approved && self.has_permission_grant && self.has_warranty_disclaimer
}

///|
pub fn LicenseFacts::to_markdown(self : LicenseFacts) -> String {
  let mut out = "## License Facts\n\n"
  out = out + "- SPDX: " + self.spdx_id + "\n"
  out = out + "- OSI approved: " + bool_text(self.osi_approved) + "\n"
  out = out + "- Has copyright: " + bool_text(self.has_copyright) + "\n"
  out = out +
    "- Has permission grant: " +
    bool_text(self.has_permission_grant) +
    "\n"
  out = out +
    "- Has warranty disclaimer: " +
    bool_text(self.has_warranty_disclaimer) +
    "\n"
  out = out + "- Has patent grant: " + bool_text(self.has_patent_grant) + "\n"
  out = out +
    "- Completeness score: " +
    self.completeness_score().to_string() +
    "\n"
  out
}

///|
fn detect_license_family(lower : String) -> LicenseFamily {
  if contains(lower, "mit license") &&
    contains(lower, "permission is hereby granted") {
    MIT
  } else if contains(lower, "apache license") && contains(lower, "version 2.0") {
    Apache2
  } else if contains(lower, "mozilla public license") && contains(lower, "2.0") {
    MPL2
  } else if contains(lower, "redistribution and use in source and binary forms") &&
    contains(lower, "neither the name") {
    BSD3
  } else if contains(lower, "redistribution and use in source and binary forms") {
    BSD2
  } else {
    UnknownLicense
  }
}

///|
fn license_spdx(family : LicenseFamily) -> String {
  match family {
    MIT => "MIT"
    Apache2 => "Apache-2.0"
    BSD2 => "BSD-2-Clause"
    BSD3 => "BSD-3-Clause"
    MPL2 => "MPL-2.0"
    UnknownLicense => "UNKNOWN"
  }
}

///|
fn license_is_osi(family : LicenseFamily) -> Bool {
  match family {
    MIT => true
    Apache2 => true
    BSD2 => true
    BSD3 => true
    MPL2 => true
    UnknownLicense => false
  }
}

///|
pub fn license_family_name(family : LicenseFamily) -> String {
  match family {
    MIT => "MIT"
    Apache2 => "Apache-2.0"
    BSD2 => "BSD-2-Clause"
    BSD3 => "BSD-3-Clause"
    MPL2 => "MPL-2.0"
    UnknownLicense => "unknown"
  }
}

///|
pub fn license_notice_template(
  project : String,
  holder : String,
  year : Int,
) -> String {
  "Copyright (c) " +
  year.to_string() +
  " " +
  holder +
  "\n\n" +
  project +
  " is distributed under the MIT License."
}

///|
pub fn license_compatibility_note(
  project : LicenseFacts,
  dependency : LicenseFacts,
) -> String {
  if !project.osi_approved || !dependency.osi_approved {
    "manual license review required"
  } else if project.family == MIT {
    "compatible for common open source redistribution"
  } else if project.family == Apache2 && dependency.family == MIT {
    "compatible, keep MIT notice for the dependency"
  } else if project.family == MIT && dependency.family == Apache2 {
    "compatible in many cases, check patent and notice obligations"
  } else {
    "likely compatible, keep original notices"
  }
}