; Installer script for SCPkg, v2 hardening pass.
; Double-click Install_SCPkg.info on Workbench and the AmigaOS
; Installation Utility (C:Installer) runs this script.
;
; Reference: https://wiki.amigaos.net/wiki/Installation_Utility
;
; This hardened installer:
;  - refuses to continue if SCPkg is still running
;  - refuses to continue if required payload files are missing
;  - distinguishes an existing SCPkg drawer from a same-named file
;  - makes Fresh install clean SCPkg-managed files and generated state
;  - seeds scpkg.prefs from data/scpkg.prefs, then overrides install_dir
;    to match the chosen destination volume
;  - optionally installs bundled ARexx example scripts under rexx/
;
; The cleanup is deliberately conservative: it removes files and drawers
; managed by SCPkg, but does not recursively delete arbitrary unknown user
; content that may have been placed in the installation drawer.
;

(complete 0)

;-----------------------------------------------------------------
; 0. Pick installer language. The choice drives every prompt below.
;    SCPkg itself follows the user's AmigaOS Locale preferences by
;    default (language=system in scpkg.prefs). ASCII-only Spanish
;    (no accents) so the file stays encoding-safe across editors.
;-----------------------------------------------------------------

(set lang
    (askchoice
        (prompt "Idioma del instalador / Installer language:")
        (help "Selecciona el idioma para los mensajes del instalador. SCPkg usara por defecto el idioma configurado en las preferencias Locale de AmigaOS.\n\nPick the installer language. SCPkg itself defaults to the language configured in AmigaOS Locale preferences.")
        (choices "Espanol" "English")
        (default 0)
    )
)

(if (= lang 1)
    (
        ; ---- English strings ----
        (set #help-where
            "Choose where SCPkg should be installed. A drawer named 'SCPkg' will be created under the destination if it is not already present. The recommended location is Work: -- this keeps SCPkg out of system assigns."
        )
        (set #help-mode
            "Update preserves your scpkg.prefs, installed.db, downloads, cache, and install manifests, then refreshes the program, guides, and catalog. Fresh install removes SCPkg-managed files and generated state first, including prefs, installed.db, downloads, cache, install manifests, logs, guides, and catalogs. Unknown files in the SCPkg drawer are left alone."
        )
        (set #help-prefs
            "Seeds scpkg.prefs from data/scpkg.prefs. The final install_dir line is adjusted to the chosen destination volume, for example Work:Games/ when installing under Work:. You can edit these values later in SCPkg's Prefs requester."
        )
        (set #help-rexx
            "SCPkg ships small ARexx example scripts under data/rexx. Install them to the SCPkg/rexx/ drawer if you want ready-to-run examples for the ARexx port. They are optional and can be copied later from the distribution drawer."
        )
        (set #ask-where     "Where should SCPkg be installed?\nA new SCPkg drawer will be created if needed.")
        (set #ask-rexx      "SCPkg provides an ARexx port for automating tasks from the CLI.\n\nThe distribution also includes example scripts for curious users.\n\nInstall the example ARexx scripts now?")
        (set #choice-update "Update (preserve prefs, db, downloads and cache)")
        (set #choice-fresh  "Fresh install (reset SCPkg-managed state)")
        (set #choice-abort  "Abort")
        (set #choice-rexx-yes "Yes, install ARexx examples")
        (set #choice-rexx-no  "No")
        (set #msg-abort     "SCPkg installation cancelled by user.")
        ; SCPKG-0186: shown once after Update installs so users know
        ; locale.library may still serve the old cached Spanish catalog
        ; until the next reboot.
        (set #msg-catalog-cache
            "Update install complete.\n\nIf SCPkg shows stale Spanish strings, reboot your Amiga. locale.library caches catalogs in memory and only drops them on reboot."
        )
    )
    (
        ; ---- Spanish strings (ASCII-only, no accents) ----
        (set #help-where
            "Elige donde se instalara SCPkg. Se creara un directorio llamado 'SCPkg' bajo el destino si no existe ya. La ubicacion recomendada es Work: -- mantiene SCPkg fuera de las asignaciones del sistema."
        )
        (set #help-mode
            "Actualizar conserva scpkg.prefs, installed.db, downloads, cache y manifiestos de instalacion, y solo refresca el programa, las guias y el catalogo. Instalacion limpia elimina primero los ficheros y estado gestionados por SCPkg, incluyendo prefs, installed.db, downloads, cache, manifiestos, logs, guias y catalogos. Los ficheros desconocidos dentro del directorio SCPkg se dejan intactos."
        )
        (set #help-prefs
            "Crea scpkg.prefs desde data/scpkg.prefs. La linea final install_dir se ajusta al volumen elegido, por ejemplo Work:Games/ al instalar bajo Work:. Puedes editar estos valores despues desde Preferencias en SCPkg."
        )
        (set #help-rexx
            "SCPkg incluye scripts ARexx de ejemplo en data/rexx. Instalalos en el directorio SCPkg/rexx/ si quieres ejemplos listos para probar el puerto ARexx. Son opcionales y se pueden copiar luego desde el directorio de distribucion."
        )
        (set #ask-where     "Donde quieres instalar SCPkg?\nSe creara un directorio SCPkg si hace falta.")
        (set #ask-rexx      "Este software dispone de un puerto ARexx para automatizar tareas via CLI.\n\nJunto a el se distribuyen una serie de scripts de ejemplo para el usuario curioso.\n\nQuieres instalar los scripts ARexx de ejemplo ahora?")
        (set #choice-update "Actualizar (conservar prefs, db, downloads y cache)")
        (set #choice-fresh  "Instalacion limpia (reiniciar estado de SCPkg)")
        (set #choice-abort  "Abortar")
        (set #choice-rexx-yes "Si, instalar ejemplos ARexx")
        (set #choice-rexx-no  "No")
        (set #msg-abort     "Instalacion de SCPkg cancelada por el usuario.")
        ; SCPKG-0186: ver bloque ingles.
        (set #msg-catalog-cache
            "Actualizacion completada.\n\nSi SCPkg muestra textos en espanol antiguos, reinicia tu Amiga. locale.library cachea los catalogos en memoria y solo los libera al reiniciar."
        )
    )
)

;-----------------------------------------------------------------
; 1. Validate required files before touching the destination.
;-----------------------------------------------------------------

(complete 5)

(if (not (= (exists "data/SCPkg") 1))
    (abort
        (if (= lang 1)
            "Required file data/SCPkg is missing. This installation archive is incomplete."
            "Falta el fichero obligatorio data/SCPkg. Este archivo de instalacion esta incompleto."
        )
    )
)

(if (not (= (exists "data/SCPkg.info") 1))
    (abort
        (if (= lang 1)
            "Required file data/SCPkg.info is missing. This installation archive is incomplete."
            "Falta el fichero obligatorio data/SCPkg.info. Este archivo de instalacion esta incompleto."
        )
    )
)

(if (not (= (exists "data/SCPkgLaunch") 1))
    (abort
        (if (= lang 1)
            "Required file data/SCPkgLaunch is missing. This installation archive is incomplete."
            "Falta el fichero obligatorio data/SCPkgLaunch. Este archivo de instalacion esta incompleto."
        )
    )
)

(if (not (= (exists "data/SCPkgIsRunning") 1))
    (abort
        (if (= lang 1)
            "Required file data/SCPkgIsRunning is missing. This installation archive is incomplete."
            "Falta el fichero obligatorio data/SCPkgIsRunning. Este archivo de instalacion esta incompleto."
        )
    )
)

(if (not (= (exists "data/scpkg.prefs") 1))
    (abort
        (if (= lang 1)
            "Required file data/scpkg.prefs is missing. This installation archive is incomplete."
            "Falta el fichero obligatorio data/scpkg.prefs. Este archivo de instalacion esta incompleto."
        )
    )
)

(if (not (= (exists "data/SCPkg.guide") 1))
    (abort
        (if (= lang 1)
            "Required file data/SCPkg.guide is missing. This installation archive is incomplete."
            "Falta el fichero obligatorio data/SCPkg.guide. Este archivo de instalacion esta incompleto."
        )
    )
)

(if (not (= (exists "data/SCPkg.guide.en") 1))
    (abort
        (if (= lang 1)
            "Required file data/SCPkg.guide.en is missing. This installation archive is incomplete."
            "Falta el fichero obligatorio data/SCPkg.guide.en. Este archivo de instalacion esta incompleto."
        )
    )
)

(if (not (= (exists "data/Catalogs/spanish/SCPkg.catalog") 1))
    (abort
        (if (= lang 1)
            "Required file data/Catalogs/spanish/SCPkg.catalog is missing. This installation archive is incomplete."
            "Falta el fichero obligatorio data/Catalogs/spanish/SCPkg.catalog. Este archivo de instalacion esta incompleto."
        )
    )
)

; Detect the public MUI/ARexx port before touching the destination.
(if (= (run "data/SCPkgIsRunning >NIL:") 5)
    (abort
        (if (= lang 1)
            "SCPkg is currently running. Close SCPkg, then run the installer again."
            "SCPkg esta ejecutandose. Cierra SCPkg y vuelve a iniciar la instalacion."
        )
    )
)

;-----------------------------------------------------------------
; 2. Ask where to install.
;-----------------------------------------------------------------

(complete 10)

(set @default-dest "Work:")

(set destbase
    (askdir
        (prompt #ask-where)
        (help #help-where)
        (default @default-dest)
        (disk)
    )
)

(set scpkgdir (tackon destbase "SCPkg"))
(set prefs-target (tackon scpkgdir "scpkg.prefs"))
(set downloads-dir (tackon scpkgdir "downloads"))
(set cache-dir (tackon scpkgdir "cache"))
(set installed-dir (tackon scpkgdir "installed"))

; Spanish catalog now lives under LOCALE:
(set catalog-spanish-dir "LOCALE:Catalogs/espaol")
(set rexx-dir (tackon scpkgdir "rexx"))

;-----------------------------------------------------------------
; migration sweep. Runs on BOTH fresh and update modes so users
; upgrading from an older .lha don't end up with locale.library
; loading the stale PROGDIR catalog. PROGDIR is searched; BEFORE
; LOCALE: in OpenCatalogA so the legacy copy wins until it's gone.
; (all) makes the delete recursive; (optional force) lets the
; script continue if the dir was never created.
;-----------------------------------------------------------------

(set legacy-catalog-dir (tackon scpkgdir "Catalogs"))
(if (= (exists legacy-catalog-dir) 2)
    (delete legacy-catalog-dir (all) (infos) (optional force))
)

;-----------------------------------------------------------------
; 3. Detect an existing install and ask the user what to do.
;-----------------------------------------------------------------

(complete 20)

(set install-mode 0)
(set scpkg-exists (exists scpkgdir))

(if (= scpkg-exists 1)
    (abort
        (if (= lang 1)
            ("A file named %s already exists. SCPkg needs this path to be a drawer. Rename or delete that file, then run the installer again." scpkgdir)
            ("Ya existe un fichero llamado %s. SCPkg necesita que esa ruta sea un directorio. Renombra o borra ese fichero y ejecuta el instalador de nuevo." scpkgdir)
        )
    )
)

(if (= scpkg-exists 2)
    (
        (set install-mode
            (askchoice
                (prompt
                    (if (= lang 1)
                        ("An SCPkg drawer already exists at %s.\n\nWhat do you want to do?" scpkgdir)
                        ("Ya existe un directorio SCPkg en %s.\n\nQue quieres hacer?" scpkgdir)
                    )
                )
                (help #help-mode)
                (choices #choice-update #choice-fresh #choice-abort)
                (default 0)
            )
        )
        (if (= install-mode 2)
            (abort #msg-abort)
        )
    )
    ; not present -- fresh install branch
    (set install-mode 1)
)

;-----------------------------------------------------------------
; 4. Fresh install cleanup. This resets SCPkg's own files and state.
;-----------------------------------------------------------------

(complete 30)

(if (= install-mode 1)
    (
        (delete (tackon scpkgdir "SCPkg") (infos) (optional force))
        (delete (tackon scpkgdir "SCPkgLaunch") (optional force))
        (delete (tackon scpkgdir "SCPkg.guide") (infos) (optional force))
        (delete (tackon scpkgdir "SCPkg.guide.en") (optional force))
        (delete prefs-target (optional force))
        (delete (tackon scpkgdir "installed.db") (optional force))
        (delete (tackon scpkgdir "scpkg.log") (optional force))
        (delete (tackon scpkgdir "scpkg.boot") (optional force))

        (if (= (exists downloads-dir) 2)
            (
                (foreach downloads-dir "#?"
                    (delete (tackon downloads-dir @each-name) (infos) (optional force))
                )
                (delete downloads-dir (infos) (optional force))
            )
        )

        (if (= (exists cache-dir) 2)
            (
                (foreach cache-dir "#?"
                    (delete (tackon cache-dir @each-name) (infos) (optional force))
                )
                (delete cache-dir (infos) (optional force))
            )
        )

        (if (= (exists installed-dir) 2)
            (
                (foreach installed-dir "#?"
                    (delete (tackon installed-dir @each-name) (infos) (optional force))
                )
                (delete installed-dir (infos) (optional force))
            )
        )

        ; only delete OUR catalog file under LOCALE:,
        ; never the shared Catalogs/<lang>/ directory itself.
        (delete (tackon catalog-spanish-dir "SCPkg.catalog") (optional force))

        (if (= (exists rexx-dir) 2)
            (
                (foreach rexx-dir "#?"
                    (delete (tackon rexx-dir @each-name) (infos) (optional force))
                )
                (delete rexx-dir (infos) (optional force))
            )
        )
    )
)

;-----------------------------------------------------------------
; 5. Create the SCPkg drawer and expected subdrawers.
;-----------------------------------------------------------------

(complete 45)

(makedir scpkgdir (infos))
(makedir downloads-dir)
(makedir cache-dir)
(makedir installed-dir)
(makedir catalog-spanish-dir)

;-----------------------------------------------------------------
; 6. Copy program, icon, guides, and catalog. These are required,
;    so copy failures should stop the installer.
;-----------------------------------------------------------------

(complete 60)

(copyfiles
    (source "data/SCPkg")
    (dest scpkgdir)
    (optional force)
)

(copyfiles
    (source "data/SCPkg.info")
    (dest scpkgdir)
    (optional force)
)

(copyfiles
    (source "data/SCPkgLaunch")
    (dest scpkgdir)
    (optional force)
)

(copyfiles
    (source "data/SCPkg.guide")
    (dest scpkgdir)
    (optional force)
)

(copyfiles
    (source "data/SCPkg.guide.en")
    (dest scpkgdir)
    (optional force)
)

(if (= (exists "data/SCPkg.guide.info") 1)
    (copyfiles
        (source "data/SCPkg.guide.info")
        (dest scpkgdir)
        (optional force)
    )
)

; SCPKG-0215: optional default cover placeholder (shown when a package
; ships no cover.iff and show_installed_covers is on). Older bundles
; without it just show an empty slot.
(if (= (exists "data/SCPkg_nocover.iff") 1)
    (copyfiles
        (source "data/SCPkg_nocover.iff")
        (dest scpkgdir)
        (optional force)
    )
)

(copyfiles
    (source "data/Catalogs/spanish/SCPkg.catalog")
    (dest catalog-spanish-dir)
    (optional force)
)

; SCPKG-0186: dropped the C:Avail FLUSH call that used to live here.
; It did not actually purge locale.library's in-memory catalog cache
; (FLUSH only expunges libraries whose open count is zero, and
; locale.library is always in use by the system). Worse, the
; AvailMem(MEMF_LARGEST) walk Avail runs at the end raised
; AN_MemoryInsane on systems with pre-existing free-list corruption
; from other apps run earlier in the same session. The honest fix for
; stale Spanish strings after an Update install is a reboot; we tell
; the user instead of running a dangerous best-effort op.
(if (= install-mode 0)
    (message #msg-catalog-cache)
)

;-----------------------------------------------------------------
; 7. Optional ARexx example scripts.
;-----------------------------------------------------------------

(complete 72)

(set install-rexx 1)
(if (= (exists "data/rexx") 2)
    (set install-rexx
        (askchoice
            (prompt #ask-rexx)
            (help #help-rexx)
            (choices #choice-rexx-yes #choice-rexx-no)
            (default 0)
        )
    )
)

(if (= install-rexx 0)
    (
        (makedir rexx-dir)
        (copyfiles
            (source "data/rexx")
            (dest rexx-dir)
            (pattern "#?.rexx")
            (files)
            (optional force)
        )
    )
)

;-----------------------------------------------------------------
; 8. Seed scpkg.prefs. Always written on Fresh; only written on Update
;    when the destination has no prefs file.
;
;    data/scpkg.prefs remains the source of truth for stock defaults.
;    The appended install_dir line intentionally overrides the template's
;    Work:Games/ default; SCPkg's parser applies later duplicate keys last.
;-----------------------------------------------------------------

(complete 85)

(if (or (= install-mode 1) (not (exists prefs-target)))
    (textfile
        (dest prefs-target)
        (include "data/scpkg.prefs")
        (append ("\ninstall_dir=%s/\n" (tackon destbase "Games")))
        (help #help-prefs)
    )
)

;-----------------------------------------------------------------
; 9. Final report.
;-----------------------------------------------------------------

(complete 100)

(exit
    (if (= lang 1)
        ("SCPkg has been installed to %s.\n\nDouble-click SCPkg to launch it, then use Prefs to set your repository URL if needed." scpkgdir)
        ("SCPkg se ha instalado en %s.\n\nHaz doble-click en SCPkg para lanzarlo, despues usa Preferencias para configurar la URL del repositorio si hace falta." scpkgdir)
    )
)
