val scala3: String = "3.3.1"

ThisBuild / organizationName     := "garrity software"
ThisBuild / organization         := "gs"
ThisBuild / organizationHomepage := Some(url("https://garrity.co/"))
ThisBuild / scalaVersion         := scala3
ThisBuild / versionScheme        := Some("early-semver")

externalResolvers := Seq(
  "Garrity Software Releases" at "https://maven.garrity.co/releases"
)

val ProjectName: String = "gs-blob"
val Description: String = "Garrity Software Blob Data Type"

/** Helper to extract the value from `-Dproperty=value`.
  *
  * @param name
  *   The property name.
  * @param conv
  *   The conversion function to the output type.
  * @return
  *   The converted value, or `None` if no value exists.
  */
def getProperty[A](
  name: String,
  conv: String => A
): Option[A] =
  Option(System.getProperty(name)).map(conv)

/** Use `sbt -Dversion=<version>` to provide the version, minus the SNAPSHOT
  * modifier. This is the typical approach for producing releases.
  */
val VersionProperty: String = "version"

/** Use `sbt -Drelease=true` to trigger a release build.
  */
val ReleaseProperty: String = "release"

/** The value of `-Dversion=<value>`.
  *
  * @return
  *   The version passed as input to SBT.
  */
lazy val InputVersion: Option[String] =
  getProperty(VersionProperty, identity)

/** @return
  *   "-SNAPSHOT" if this is NOT a release, empty string otherwise.
  */
lazy val Modifier: String =
  if (getProperty(ReleaseProperty, _.toBoolean).getOrElse(false)) ""
  else "-SNAPSHOT"

/** Version used if no version is passed as input. This helps with default/local
  * builds.
  */
val DefaultVersion: String = "0.1.0-SNAPSHOT"

/** This is the output version of the published artifact. If this build is not a
  * release, the suffix "-SNAPSHOT" will be appended.
  *
  * @return
  *   The project version.
  */
lazy val SelectedVersion: String =
  InputVersion
    .map(v => s"$v$Modifier")
    .getOrElse(DefaultVersion)

/** The major version (first segment) value. Used to label releases.
  *
  * @return
  *   The major version of the project.
  */
lazy val MajorVersion: String =
  SelectedVersion.split('.').apply(0)

val sharedSettings = Seq(
  scalaVersion := scala3,
  version      := SelectedVersion
)

lazy val publishSettings = Seq(
  publishMavenStyle      := true,
  Test / publishArtifact := false,
  pomIncludeRepository   := Function.const(false),
  scmInfo := Some(
    ScmInfo(
      url(s"https://git.garrity.co/garrity-software/$ProjectName"),
      s"git@git.garrity.co:garrity-software/$ProjectName.git"
    )
  ),
  description := Description,
  licenses := List(
    "Apache 2.0" -> url("https://www.apache.org/licenses/LICENSE-2.0.html")
  ),
  homepage := Some(
    url(s"https://git.garrity.co/garrity-software/$ProjectName")
  ),
  publishTo := {
    val repo = "https://maven.garrity.co/"
    if (SelectedVersion.endsWith("SNAPSHOT"))
      Some("Garrity Software Maven" at repo + "snapshots")
    else Some("Garrity Software Maven" at repo + "releases")
  }
)

lazy val testSettings = Seq(
  libraryDependencies ++= Seq(
    "org.scalameta" %% "munit" % "1.0.0-M10" % Test
  )
)

lazy val `gs-blob` = project
  .in(file("."))
  .settings(sharedSettings)
  .settings(publishSettings)
  .settings(testSettings)
  .settings(name := s"$ProjectName-v$MajorVersion")

ThisBuild / scalacOptions ++= Seq(
  "-encoding",
  "utf8",         // Set source file character encoding.
  "-deprecation", // Emit warning and location for usages of deprecated APIs.
  "-feature", // Emit warning and location for usages of features that should be imported explicitly.
  "-explain", // Explain errors in more detail.
  "-unchecked", // Enable additional warnings where generated code depends on assumptions.
  "-explain-types",           // Explain type errors in more detail.
  "-Xfatal-warnings",         // Fail the compilation if there are any warnings.
  "-language:strictEquality", // Enable multiversal equality (require CanEqual)
  "-Wunused:implicits",       // Warn if an implicit parameter is unused.
  "-Wunused:explicits",       // Warn if an explicit parameter is unused.
  "-Wunused:imports",         // Warn if an import selector is not referenced.
  "-Wunused:locals",          // Warn if a local definition is unused.
  "-Wunused:privates",        // Warn if a private member is unused.
  "-Ysafe-init" // Enable the experimental safe initialization check.
)