###############################################################################
#
# pkgd.eagle --
#
# Extensible Adaptable Generalized Logic Engine (Eagle)
# Package Downloader Client
#
# Copyright (c) 2007-2012 by Joe Mistachkin.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: $
#
###############################################################################
#
# NOTE: Use our own namespace here because even though we do not directly
#       support namespaces ourselves, we do not want to pollute the global
#       namespace if this script actually ends up being evaluated in Tcl.
#
namespace eval ::PackageDownloader {
  proc setupDownloadVars {} {
    #
    # NOTE: Prevent progress messages from being displayed while downloading
    #       from the repository, etc?  By default, this is enabled.
    #
    variable quiet; # DEFAULT: true
    if {![info exists quiet]} then {
      set quiet true
    }
    #
    # NOTE: The base URI for the package distribution web site.
    #
    variable baseUri; # DEFAULT: https://urn.to/r/pkgr
    if {![info exists baseUri]} then {
      set baseUri https://urn.to/r/pkgr
    }
    #
    # NOTE: The URI where a single package file may be found.  This file will
    #       belong to a specific version of one package.
    #
    variable downloadUri; # DEFAULT: ${baseUri}?...&filename=${fileName}
    if {![info exists downloadUri]} then {
      set downloadUri {${baseUri}?download&ci=trunk&filename=${fileName}}
    }
    #
    # NOTE: The root directory where any persistent packages will be saved.
    #
    variable persistentDirectory; # DEFAULT: [getPersistentRootDirectory]
    if {![info exists persistentDirectory]} then {
      set persistentDirectory [getPersistentRootDirectory]
    }
  }
  proc getPersistentRootDirectory {} {
    #
    # NOTE: Return a directory parallel to the one containing the library
    #       directory.
    #
    return [file join [file dirname [info library]] pkgr]
  }
  proc addToAutoPath { language directory } {
    #
    # NOTE: Add the specified directory to the auto-path if not already
    #       present.
    #
    if {[string length $language] == 0 || $language eq "eagle"} then {
      if {[isEagle]} then {
        if {![info exists ::auto_path] || \
            [lsearch -exact $::auto_path $directory] == -1} then {
          lappend ::auto_path $directory
        }
      } else {
        ::PackageRepository::eagleMustBeReady
        eagle [string map [list %directory% $directory] {
          if {![info exists ::auto_path] || \
              [lsearch -exact $::auto_path {%directory%}] == -1} then {
            lappend ::auto_path {%directory%}
          }
        }]
      }
    } elseif {$language eq "tcl"} then {
      if {[isEagle]} then {
        tcl eval [tcl master] [string map [list %directory% $directory] {
          if {![info exists ::auto_path] || \
              [lsearch -exact $::auto_path {%directory%}] == -1} then {
            lappend ::auto_path {%directory%}
          }
        }]
      } else {
        if {![info exists ::auto_path] || \
            [lsearch -exact $::auto_path $directory] == -1} then {
          lappend ::auto_path $directory
        }
      }
    } else {
      error "unsupported language, no idea how to modify auto-path"
    }
  }
  proc downloadFiles { language version fileNames persistent } {
    variable baseUri
    variable downloadUri
    variable persistentDirectory
    variable quiet
    if {$persistent} then {
      set downloadRootDirectory [file join $persistentDirectory]
    } else {
      global env
      if {[info exists env(PKGD_TEMP)]} then {
        set downloadRootDirectory [file join $env(PKGD_TEMP) pkgr]
      } elseif {[info exists env(TEMP)]} then {
        set downloadRootDirectory [file join $env(TEMP) pkgr]
      } elseif {[info exists env(TMP)]} then {
        set downloadRootDirectory [file join $env(TMP) pkgr]
      } else {
        error "please set PKGD_TEMP (via environment) to temporary directory"
      }
    }
    set downloadDirectories [list]
    foreach fileName $fileNames {
      if {[string length $fileName] == 0 || \
          [file pathtype $fileName] ne "relative"} then {
        error [appendArgs \
            "bad file name \"" $fileName "\", not relative"]
      }
      set directoryParts [file split [file dirname $fileName]]
      if {[llength $directoryParts] == 0} then {
        error [appendArgs \
            "bad file name \"" $fileName "\", no directory parts"]
      }
      set downloadDirectory [eval file join \
          [list $downloadRootDirectory] $directoryParts]
      set downloadFileName [file join $downloadDirectory \
          [file tail $fileName]]
      if {!$persistent} then {
        catch {file delete $downloadFileName}
      }
      file mkdir [file dirname $downloadFileName]
      set fileName [file join $language $version $fileName]
      set uri [subst $downloadUri]
      if {[isEagle]} then {
        writeFile $downloadFileName [interp readorgetscriptfile -- "" $uri]
      } else {
        writeFile $downloadFileName [::PackageRepository::getFileViaHttp \
            $uri 10 stdout $quiet]
      }
      lappend downloadDirectories [file dirname $downloadDirectory]
    }
    set downloadDirectories [lsort -unique $downloadDirectories]
    foreach downloadDirectory $downloadDirectories {
      addToAutoPath $language $downloadDirectory
    }
  }
  #
  # NOTE: Setup the variables, within this namespace, used by this script.
  #
  setupDownloadVars
  #
  # NOTE: This package requires the package repository client package.
  #
  package require Eagle.Package.Repository
  #
  # NOTE: Provide the package to the interpreter.
  #
  package provide Eagle.Package.Downloader \
    [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}]
}