# Runtime environment for modding/src/mdlp/ (the first-party Mod Definition
# Language Processor - see ../README.md): builds mdlp from source and runs it
# against modding/mods/ to produce modding/dist/mods/. Kept as its own image,
# separate from hacked-build-image/, because mod processing is expected to
# grow its own external tool dependencies (image/audio conversion, etc.)
# independent of hacked's own GTK/GLFW/mingw toolchain.
FROM ubuntu:22.04

# go.mod's own "go" directive is a minimum toolchain version, not a version to
# fetch - pin a stable release that already satisfies it so `go build` never
# needs to fetch a newer toolchain over the network at build time.
ARG GO_VERSION=1.27.1

# patch: applies src/hacked-patches/ to the scratch copy of hacked/ that
# process-mods.sh (and ../gen_animgallery.sh) stage before building against
# it - see stage-hacked.sh. python3/pip: runs the AI upscaler below via
# plain CPU inference (ONNX Runtime). Not a Vulkan-based tool: this image
# has no real GPU, and Vulkan software emulation (Mesa lavapipe) gives
# wrong colors for ML inference workloads.
RUN apt-get update \
    && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
        ca-certificates curl gosu patch python3 python3-pip \
    && rm -rf /var/lib/apt/lists/*
RUN pip3 install --no-cache-dir onnxruntime pillow numpy scipy

# The AI upscaler models for mdlp's upscale mod type (see ../README.md
# section 4), selected per mod by a bitmaps/*.json file's own "model" field
# (upscaleDef in ../src/mdlp/upscale.go) - upscale_batch.py resolves a name
# straight to $UPSCALE_MODELS_DIR/<name>.onnx, and picks tiled or single-pass
# inference based on each model's own declared ONNX input shape (fixed vs
# dynamic height/width), so adding another model here needs no code change.
# Each model's RGB output is re-quantized to SS1's fixed 256-color palette
# with Floyd-Steinberg dithering (imageToBitmap in ../src/mdlp/upscale.go),
# not a plain nearest-color map - without it, any model's smooth gradients
# can land on a visibly wrong, much darker palette entry in a solid patch
# rather than unnoticeable dithering noise.
# All three are BSD-3-Clause ONNX exports of xinntao/Real-ESRGAN checkpoints:
# - realesrgan-x4plus-anime: a 6-block RRDBNet trained on flat-color
#   illustration, keeping hard sprite edges rather than smoothing them the
#   way a photo- or video-denoising model would. Dynamic input shape. Default
#   choice - sharpest result on most sprites.
# - realesrgan-x4plus: the general-purpose photo checkpoint (16.7M-param
#   RRDBNet). Fixed 128x128 input, needs tiling for anything larger, and
#   much slower than the other two. Worth trying when the anime model
#   mis-renders a specific sprite, but can itself mis-render different ones.
# - realesr-general-x4v3: a compact 1.2M-param SRVGGNet, dynamic input
#   shape, ~100x faster than realesrgan-x4plus. Noticeably softer than
#   either RRDBNet model, but the most robust against both models' failure
#   modes - the model to reach for on a specific sprite neither RRDBNet
#   model renders cleanly, not as a blanket replacement.
ARG UPSCALE_MODEL_ANIME_URL=https://huggingface.co/skillsafe-ai/realesrgan-x4plus-anime-6b/resolve/main/model.onnx
ARG UPSCALE_MODEL_GENERAL_URL=https://huggingface.co/qualcomm/Real-ESRGAN-x4plus/resolve/6f5749d5adff39de0127e42bc45c8ec8e6f76a66/Real-ESRGAN-x4plus.onnx
ARG UPSCALE_MODEL_COMPACT_URL=https://huggingface.co/jonathanst29/tinier-upscale-models/resolve/main/realesr-general-x4v3.onnx
RUN mkdir -p /opt/upscale-models \
    && curl -sSL -o /opt/upscale-models/realesrgan-x4plus-anime.onnx "$UPSCALE_MODEL_ANIME_URL" \
    && curl -sSL -o /opt/upscale-models/realesrgan-x4plus.onnx "$UPSCALE_MODEL_GENERAL_URL" \
    && curl -sSL -o /opt/upscale-models/realesr-general-x4v3.onnx "$UPSCALE_MODEL_COMPACT_URL"
COPY mdlp-image/upscale_batch.py /usr/local/bin/upscale_batch.py
RUN chmod 755 /usr/local/bin/upscale_batch.py
ENV UPSCALE_MODELS_DIR=/opt/upscale-models

RUN curl -sSLO "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz" \
    && tar -C /usr/local -xzf "go${GO_VERSION}.linux-amd64.tar.gz" \
    && rm "go${GO_VERSION}.linux-amd64.tar.gz"
ENV PATH=/usr/local/go/bin:${PATH}
ENV GOTOOLCHAIN=local
ENV GOPATH=/opt/go

# Populates /opt/go/pkg/mod with every dependency mdlp/go.mod pins, so the
# container never needs network access to build it. mdlp/go.mod replaces
# github.com/inkyblackness/hacked with the local ../hacked (see ../README.md),
# so that module's own go.mod/go.sum have to be present too for dependency
# resolution - only these two go.mod/go.sum pairs are copied in for this, not
# the rest of either source tree, so editing .go files doesn't invalidate
# this layer's cache.
COPY src/hacked/go.mod src/hacked/go.sum /tmp/mdlp-deps/hacked/
COPY src/mdlp/go.mod src/mdlp/go.sum /tmp/mdlp-deps/mdlp/
RUN cd /tmp/mdlp-deps/mdlp && go mod download && rm -rf /tmp/mdlp-deps

COPY mdlp-image/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
COPY mdlp-image/process-mods.sh /usr/local/bin/process-mods.sh
# 755, not +x: see hacked-build-image/Dockerfile's identical comment - the
# entrypoint drops to a `builder` user matching the host's UID/GID, which is
# never in these root-owned files' group.
RUN chmod 755 /usr/local/bin/docker-entrypoint.sh /usr/local/bin/process-mods.sh

WORKDIR /workspace/modding
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
CMD ["/usr/local/bin/process-mods.sh"]

# Marks a shell as already running inside this image, same convention as
# hacked-build-image/Dockerfile - lets ../Makefile compile directly instead
# of trying to docker-run this image again from inside itself.
ENV MDLP_IMAGE=1
