---
parameters:
  - name: terraformVersion
    default: 'latest'

steps:
  - pwsh: |
      $TF_VERSION = $env:TF_VERSION
      $TOOLS_PATH = $env:TOOLS_PATH

      $release = $null

      if($TF_VERSION -eq "latest") {
        $versionResponse = Invoke-WebRequest -Uri "https://api.releases.hashicorp.com/v1/releases/terraform?limit=20"
        if($versionResponse.StatusCode -ne "200") {
            throw "Unable to query Terraform version, please check your internet connection and try again..."
        }
        $releases = ($versionResponse).Content | ConvertFrom-Json | Where-Object -Property is_prerelease -EQ $false
        $release = $releases[0]
        $TF_VERSION = $releases[0].version
      } else {
          $versionResponse = Invoke-WebRequest -Uri "https://api.releases.hashicorp.com/v1/releases/terraform/$($TF_VERSION)"
          if($versionResponse.StatusCode -ne "200") {
              throw "Unable to query Terraform version, please check the supplied version and try again..."
          }
          $release = ($versionResponse).Content | ConvertFrom-Json
      }

      $commandDetails = Get-Command -Name terraform -ErrorAction SilentlyContinue
      if($commandDetails) {
        Write-Host "Terraform already installed in $($commandDetails.Path), checking version"
        $installedVersion = terraform version -json | ConvertFrom-Json
        Write-Host "Installed version: $($installedVersion.terraform_version) on $($installedVersion.platform)"
        if($installedVersion.terraform_version -eq $TF_VERSION) {
          Write-Host "Installed version matches required version $TF_VERSION, skipping install"
          return
        }
      }

      $unzipdir = Join-Path -Path $TOOLS_PATH -ChildPath "terraform_$TF_VERSION"
      if (Test-Path $unzipdir) {
        Write-Host "Terraform $TF_VERSION already installed."
        if($os -eq "windows") {
          $env:PATH = "$($unzipdir);$env:PATH"
        } else {
          $env:PATH = "$($unzipdir):$env:PATH"
        }
        Write-Host "##vso[task.setvariable variable=PATH]$env:PATH"
        return
      }

      $os = ""
      if ($IsWindows) {
        $os = "windows"
      }
      if($IsLinux) {
        $os = "linux"
      }
      if($IsMacOS) {
        $os = "darwin"
      }

      # Enum values can be seen here: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.architecture?view=net-7.0#fields
      $architecture = ([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture).ToString().ToLower()

      if($architecture -eq "x64") {
        $architecture = "amd64"
      }
      if($architecture -eq "x86") {
        $architecture = "386"
      }

      $osAndArchitecture = "$($os)_$($architecture)"

      $supportedOsAndArchitectures = @(
        "darwin_amd64",
        "darwin_arm64",
        "linux_386",
        "linux_amd64",
        "linux_arm64",
        "windows_386",
        "windows_amd64"
      )

      if($supportedOsAndArchitectures -notcontains $osAndArchitecture) {
        Write-Error "Unsupported OS and architecture combination: $osAndArchitecture"
        exit 1
      }

      $zipfilePath = "$unzipdir.zip"

      $url = $release.builds | Where-Object { $_.arch -eq $architecture -and $_.os -eq $os } | Select-Object -First 1 -ExpandProperty url

      if(!(Test-Path $TOOLS_PATH)) {
        New-Item -ItemType Directory -Path $TOOLS_PATH| Out-String | Write-Verbose
      }

      Invoke-WebRequest -Uri $url -OutFile "$zipfilePath" | Out-String | Write-Verbose

      Expand-Archive -Path $zipfilePath -DestinationPath $unzipdir

      $toolFileName = "terraform"

      if($os -eq "windows") {
        $toolFileName = "$($toolFileName).exe"
      }

      $toolFilePath = Join-Path -Path $unzipdir -ChildPath $toolFileName

      if($os -ne "windows") {
          $isExecutable = $(test -x $toolFilePath; 0 -eq $LASTEXITCODE)
          if(!($isExecutable)) {
            chmod +x $toolFilePath
          }
      }

      if($os -eq "windows") {
        $env:PATH = "$($unzipdir);$env:PATH"
      } else {
        $env:PATH = "$($unzipdir):$env:PATH"
      }
      Write-Host "##vso[task.setvariable variable=PATH]$env:PATH"
      Remove-Item $zipfilePath
      Write-Host "Installed Terraform version $TF_VERSION"

    displayName: Install Terraform
    env:
      TF_VERSION: $${{ parameters.terraformVersion }}
      TOOLS_PATH: $(Agent.ToolsDirectory)
