# DockerfileExtra - Combined Windmill Extra Services
#
# This image extends windmill-slim with three optional Windmill services:
# - LSP (Language Server Protocol) - Port 3001
# - Multiplayer (y-websocket) - Port 3002
# - Debugger (DAP WebSocket) - Port 3003
#
# Each service can be enabled/disabled via environment variables:
# - ENABLE_LSP=true (default: true)
# - ENABLE_MULTIPLAYER=true (default: true)
# - ENABLE_DEBUGGER=true (default: true)
#
# Build:
#   docker build -f docker/DockerfileExtra -t windmill-extra .
#
# Run:
#   docker run -p 3001:3001 -p 3002:3002 -p 3003:3003 windmill-extra

# ============================================================================
# Stage 1: Get nsjail from the nsjail image
# ============================================================================
FROM ghcr.io/windmill-labs/windmill-ee-nsjail:main AS nsjail-source

# ============================================================================
# Stage 2: Build final extra services image from windmill-slim
# ============================================================================
FROM ghcr.io/windmill-labs/windmill-ee-slim:latest AS final

ARG APP=/usr/src/app

# Install Node.js 22 (needed for LSP and multiplayer)
RUN apt-get update && apt-get install -y --no-install-recommends \
    gnupg \
    && mkdir -p /etc/apt/keyrings \
    && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
    && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" > /etc/apt/sources.list.d/nodesource.list \
    && apt-get update \
    && apt-get install -y nodejs \
    && rm -rf /var/lib/apt/lists/*

# Install additional system dependencies
# - shellcheck: for bash LSP
# - libprotobuf-dev, libnl-route-3-dev: for nsjail runtime
RUN apt-get update && apt-get install -y --no-install-recommends \
    shellcheck \
    libprotobuf-dev \
    libnl-route-3-dev \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# Install Go for gopls (Go LSP)
RUN set -eux; \
    arch="$(dpkg --print-architecture)"; arch="${arch##*-}"; \
    case "$arch" in \
    'amd64') targz='go1.21.13.linux-amd64.tar.gz' ;; \
    'arm64') targz='go1.21.13.linux-arm64.tar.gz' ;; \
    'armhf') targz='go1.21.13.linux-armv6l.tar.gz' ;; \
    *) echo >&2 "error: unsupported architecture '$arch'"; exit 1 ;; \
    esac; \
    wget "https://golang.org/dl/$targz" -nv && tar -C /usr/local -xzf "$targz" && rm "$targz"

ENV PATH="${PATH}:/usr/local/go/bin"
ENV GOBIN=/usr/local/go/bin

# Install gopls for Go LSP
RUN /usr/local/go/bin/go install -v golang.org/x/tools/gopls@latest

# Copy Deno for Deno LSP
COPY --from=denoland/deno:2.2.1 --chmod=755 /usr/bin/deno /usr/bin/deno

# Copy nsjail from nsjail image (for sandboxed debugging)
COPY --from=nsjail-source /bin/nsjail /bin/nsjail

# ============================================================================
# LSP Setup
# ============================================================================

ENV PIPENV_VENV_IN_PROJECT=1
ENV XDG_CACHE_HOME=/pyls/.cache

# Install Python packages for LSP using uv
RUN uv pip install --system --break-system-packages pipenv tornado python-lsp-jsonrpc ruff Cython

# Install Node-based language servers
RUN npm install -g diagnostic-languageserver pyright

# Setup LSP working directory
WORKDIR /pyls
COPY lsp/Pipfile .
RUN pipenv install
COPY lsp/pyls_launcher.py .

# Setup Monaco temp directory for LSP
RUN mkdir -p /tmp/monaco && chmod -R 777 /tmp/monaco
RUN cd /tmp/monaco && npm install --save-dev windmill-client

RUN mkdir -p /pyls/.cache

# ============================================================================
# Debugger Setup
# ============================================================================

WORKDIR /debugger

# Copy debugger files
COPY debugger/dap_debug_service.ts .
COPY debugger/dap_websocket_server_bun.ts .
COPY debugger/dap_websocket_server.py .
COPY debugger/nsjail.debug.config.proto .

# Install Python debugger dependencies using uv
RUN uv pip install --system --break-system-packages websockets debugpy

# ============================================================================
# Multiplayer Setup (y-websocket with connection logging)
# ============================================================================

WORKDIR /multiplayer

# Copy multiplayer server files
COPY multiplayer/package.json .
COPY multiplayer/server.mjs .

# Install dependencies
RUN npm install

# ============================================================================
# Entrypoint Setup
# ============================================================================

WORKDIR /app

# Copy entrypoint script
COPY docker/entrypoint-extra.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

# Set permissions
RUN chmod -R a+rX /usr/local && \
    chmod -R a+rX /pyls && \
    chmod -R a+rX /debugger

# Expose all service ports
EXPOSE 3001 3002 3003

# Environment variables for service control
ENV ENABLE_LSP=true
ENV ENABLE_MULTIPLAYER=true
ENV ENABLE_DEBUGGER=true
# nsjail sandboxing for debugger (requires --privileged, off by default)
ENV ENABLE_NSJAIL=false

# LSP port
ENV LSP_PORT=3001

# Multiplayer port and host
ENV MULTIPLAYER_PORT=3002
ENV HOST=0.0.0.0

# Debugger port
ENV DEBUGGER_PORT=3003

# Windmill base URL for debugger token verification
ENV WINDMILL_BASE_URL=""

ENTRYPOINT ["/entrypoint.sh"]
