#!/bin/bash
#
# Magic Mirror for Raspberry Pi 2 — One File, Double-Click, Done.
# https://the workbench (your site)
#
# This installer turns a fresh Raspberry Pi 2 (or compatible) into a working
# Magic Mirror with one download + double-click (or terminal run).
#
# Optimized for Pi 2 realities:
#   - 1 GB RAM → prefers lightweight browser kiosk mode over Electron by default
#   - armv7l (32-bit) → uses Node 18 LTS via nodesource (known good for MM on legacy Pis)
#   - Slow CPU → lots of friendly progress messages, realistic time estimates
#
# What you get after running this:
#   - ~/MagicMirror/ with a clean MagicMirror² install
#   - A polished default config.js (clock + calendar + compliments + news)
#   - Desktop icon "Magic Mirror" (double-click to launch)
#   - Auto-start on login (so a dedicated mirror Pi boots straight into the mirror)
#   - A robust kiosk launcher using Chromium in fullscreen (lighter on RAM than full Electron)
#   - Easy "quit" instructions
#
# Recommended Pi 2 OS (for best driver/compat on old hardware):
#   Raspberry Pi OS (Legacy, 32-bit) Bullseye with desktop
#   (Use Raspberry Pi Imager → choose "Raspberry Pi OS (Legacy)" → 32-bit)
#
# Usage on the Pi:
#   1. wget https://.../MagicMirror-Pi2-Installer.sh   (or download via browser)
#   2. chmod +x MagicMirror-Pi2-Installer.sh
#   3. ./MagicMirror-Pi2-Installer.sh     (or double-click the file in file manager → "Execute in Terminal")
#
# After it finishes you will have a working Magic Mirror on your screen.
# Customize by editing ~/MagicMirror/config/config.js then re-launch.
#
set -euo pipefail

# ─────────────────────────────────────────────────────────────────────────────
# Pretty output helpers
# ─────────────────────────────────────────────────────────────────────────────
if [ -t 1 ]; then
  BOLD="\033[1m"; DIM="\033[2m"; RED="\033[0;31m"; GREEN="\033[0;32m"; YELLOW="\033[0;33m"; CYAN="\033[0;36m"; RESET="\033[0m"
else
  BOLD=""; DIM=""; RED=""; GREEN=""; YELLOW=""; CYAN=""; RESET=""
fi

say() { echo -e "${CYAN}▶${RESET} $1"; }
ok()  { echo -e "${GREEN}✓${RESET} $1"; }
warn(){ echo -e "${YELLOW}⚠${RESET} $1"; }
err() { echo -e "${RED}✗${RESET} $1" >&2; }

step() {
  echo ""
  echo -e "${BOLD}${CYAN}=== $1 ===${RESET}"
}

pause_for_effect() {
  # Small human-friendly pauses on slow hardware so the user sees progress
  sleep 0.4
}

# ─────────────────────────────────────────────────────────────────────────────
# Detect environment (Pi 2 friendly)
# ─────────────────────────────────────────────────────────────────────────────
detect_pi_model() {
  local model="Unknown"
  if [ -f /proc/device-tree/model ]; then
    model=$(tr -d '\0' < /proc/device-tree/model 2>/dev/null || echo "Unknown")
  elif grep -qi "Raspberry Pi" /proc/cpuinfo 2>/dev/null; then
    model=$(grep -i "Model" /proc/cpuinfo | head -1 | cut -d: -f2 | xargs || echo "Raspberry Pi (legacy)")
  fi
  echo "$model"
}

IS_PI2=false
MODEL=$(detect_pi_model)
if echo "$MODEL" | grep -qi "Raspberry Pi 2"; then
  IS_PI2=true
fi

TOTAL_MEM_MB=$(free -m | awk 'NR==2 {print $2}')
LOW_RAM=false
if [ "$TOTAL_MEM_MB" -lt 950 ]; then
  LOW_RAM=true
fi

USER_NAME="${USER:-pi}"
HOME_DIR="${HOME:-/home/${USER_NAME}}"
TARGET_DIR="${HOME_DIR}/MagicMirror"
INSTALLER_VERSION="2026.06-pi2-v1"

# ─────────────────────────────────────────────────────────────────────────────
# Header
# ─────────────────────────────────────────────────────────────────────────────
clear || true
cat << 'HEADER'
   __  __             _      __  __ _                     
  |  \/  | __ _  __ _(_) ___|  \/  (_)_ __ _ __ ___  _ __ 
  | |\/| |/ _` |/ _` | |/ __| |\/| | | '__| '__/ _ \| '__|
  | |  | | (_| | (_| | | (__| |  | | | |  | | | (_) | |   
  |_|  |_|\__,_|\__, |_|\___|_|  |_|_|_|  |_|  \___/|_|   
                |___/                                     
HEADER
echo -e "${DIM}One-file installer for Raspberry Pi 2 — MagicMirror²${RESET}"
echo -e "${DIM}Version ${INSTALLER_VERSION} — made for The Work Bench${RESET}"
echo ""
echo "Detected: ${BOLD}${MODEL}${RESET}"
echo "Memory  : ${TOTAL_MEM_MB} MB"
if $IS_PI2; then
  echo -e "${GREEN}Pi 2 detected — installer tuned for 1 GB RAM + armv7${RESET}"
fi
if $LOW_RAM; then
  echo -e "${YELLOW}Low-RAM mode will be used (browser kiosk, not Electron)${RESET}"
fi
echo ""
echo -e "${DIM}This will take a while on a Pi 2 (Node install + npm can be 40-90 minutes).${RESET}"
echo -e "${DIM}The screen may look frozen at times — that's normal. Progress messages will appear.${RESET}"
echo ""

# Safety / confirmation
read -r -p "Ready to turn this Pi into a Magic Mirror? [Y/n] " reply
if [[ ! "$reply" =~ ^[Yy]$ ]] && [[ -n "$reply" ]]; then
  echo "Aborted by user."
  exit 0
fi

# ─────────────────────────────────────────────────────────────────────────────
# 1. System prep + swap boost (helps npm on 1 GB)
# ─────────────────────────────────────────────────────────────────────────────
step "1/8  System update & dependencies (this can be slow on Pi 2)"

say "Updating package lists..."
sudo apt-get update -y

say "Upgrading existing packages (security + firmware)..."
sudo apt-get full-upgrade -y || true

say "Installing build tools, git, browser, unclutter, and helpers..."
sudo apt-get install -y \
  git curl build-essential \
  libx11-dev libxext-dev libxtst-dev \
  unclutter xdotool \
  chromium-browser || sudo apt-get install -y chromium || true

# Increase swap for the big npm install
if [ "$TOTAL_MEM_MB" -lt 1200 ]; then
  say "Boosting swapfile to 1 GB (helps Node/npm on Pi 2)..."
  sudo dphys-swapfile swapoff 2>/dev/null || true
  echo "CONF_SWAPSIZE=1024" | sudo tee /etc/dphys-swapfile >/dev/null
  sudo dphys-swapfile setup >/dev/null || true
  sudo dphys-swapfile swapon 2>/dev/null || true
  ok "Swap increased"
fi

ok "Base system ready"

# ─────────────────────────────────────────────────────────────────────────────
# 2. Node.js 18 (nodesource — reliable armv7 builds)
# ─────────────────────────────────────────────────────────────────────────────
step "2/8  Installing Node.js 18 LTS (via nodesource)"

if command -v node >/dev/null 2>&1; then
  CURRENT_NODE=$(node -v || echo "none")
  say "Existing Node found: $CURRENT_NODE"
  if [[ "$CURRENT_NODE" =~ ^v1[6-9]|^v2[0-1] ]]; then
    ok "Node version looks compatible, skipping reinstall"
  else
    warn "Node version may be too new/old for best Pi 2 results. Installing Node 18..."
    curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
    sudo apt-get install -y nodejs
  fi
else
  say "No Node found — adding NodeSource repo for Node 18..."
  curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
  sudo apt-get install -y nodejs
fi

NODE_VER=$(node -v 2>/dev/null || echo "unknown")
NPM_VER=$(npm -v 2>/dev/null || echo "unknown")
ok "Node ${NODE_VER} / npm ${NPM_VER}"

# ─────────────────────────────────────────────────────────────────────────────
# 3. Clone / update MagicMirror
# ─────────────────────────────────────────────────────────────────────────────
step "3/8  MagicMirror² source"

if [ -d "$TARGET_DIR" ]; then
  warn "Existing MagicMirror directory found at $TARGET_DIR"
  read -r -p "Pull latest and reinstall modules? (recommended) [Y/n] " do_update
  if [[ "$do_update" =~ ^[Yy]$ ]] || [[ -z "$do_update" ]]; then
    say "Updating existing checkout..."
    cd "$TARGET_DIR"
    git fetch --all || true
    git checkout master || git checkout main || true
    git pull --ff-only || true
    # Clean node_modules to avoid arch mismatches after OS updates
    rm -rf node_modules package-lock.json 2>/dev/null || true
  else
    say "Keeping existing directory. Will still ensure modules are present."
    cd "$TARGET_DIR"
  fi
else
  say "Cloning MagicMirror² (MichMich) into ${TARGET_DIR} ..."
  git clone https://github.com/MichMich/MagicMirror.git "$TARGET_DIR"
  cd "$TARGET_DIR"
fi

ok "Source ready at $TARGET_DIR"

# ─────────────────────────────────────────────────────────────────────────────
# 4. npm install (the long one)
# ─────────────────────────────────────────────────────────────────────────────
step "4/8  Installing Node dependencies (the slow part — 30-80 min on Pi 2)"

cd "$TARGET_DIR"

say "Running npm install. This is where Pi 2 takes its time."
say "You will see lots of output. A few warnings are normal."
echo -e "${DIM}(If it appears stuck for 5+ minutes, it's probably still compiling native addons.)${RESET}"

# Use --no-optional to reduce some bloat; still pulls everything needed for core
npm install --no-optional 2>&1 | tee -a /tmp/mm-npm.log || {
  warn "npm install had errors. Trying a second time with legacy peer deps..."
  npm install --legacy-peer-deps --no-optional 2>&1 | tee -a /tmp/mm-npm.log
}

ok "npm dependencies installed"

# ─────────────────────────────────────────────────────────────────────────────
# 5. Personalized, working default config
# ─────────────────────────────────────────────────────────────────────────────
step "5/8  Creating a beautiful ready-to-use config.js"

# Ask for name once (used in compliments)
read -r -p "What's your first name? (used for friendly greetings) [Magic] " FIRST_NAME
FIRST_NAME=${FIRST_NAME:-Magic}

# Backup original sample if present
if [ -f config/config.js ]; then
  cp config/config.js "config/config.js.backup.$(date +%s)" || true
fi

# Write a clean, pretty, low-RAM-friendly config that "just works"
cat > config/config.js << CONFIGEOF
/* Magic Mirror Config — generated by the Pi 2 one-file installer
   Edit this file, then restart the mirror (close the kiosk and double-click the desktop icon again).
   Full docs: https://docs.magicmirror.builders/
*/
var config = {
  address: "0.0.0.0",          // listen on all interfaces (kiosk on same box is fine)
  port: 8080,
  basePath: "/",
  ipWhitelist: [
    "127.0.0.1",
    "::ffff:127.0.0.1",
    "::1",
    "::ffff:192.168.0.0/112",  // allow your local LAN if you want to view from phone
    "0.0.0.0/0"                // safe for a dedicated local mirror device
  ],

  useHttps: false,
  httpsPrivateKey: "",
  httpsCertificate: "",

  language: "en",
  locale: "en-US",
  timeFormat: 12,
  units: "imperial",

  serverOnly: false,   // we launch our own kiosk; keep false so the server runs

  modules: [
    {
      module: "clock",
      position: "top_left",
      config: {
        displayType: "digital",
        clockBold: true,
        showWeek: true,
        showSeconds: false,
        showPeriod: true
      }
    },
    {
      module: "calendar",
      position: "top_right",
      config: {
        maximumEntries: 6,
        maximumNumberOfDays: 14,
        fade: true,
        fadePoint: 0.25,
        calendars: [
          {
            symbol: "📅",
            url: "https://ics.calendarlabs.com/1/usa/usa.ics"   // public US holidays example (works without auth)
          }
          // Add your personal iCal URLs here (Google Calendar "secret address in iCal format", etc.)
        ]
      }
    },
    {
      module: "compliments",
      position: "lower_third",
      config: {
        compliments: {
          anytime: [
            "Hello, ${FIRST_NAME}.",
            "Looking good today.",
            "The mirror is happy to see you.",
            "You are doing great."
          ],
          morning: [
            "Good morning, ${FIRST_NAME}.",
            "Have a wonderful day.",
            "Rise and shine."
          ],
          afternoon: [
            "Good afternoon, ${FIRST_NAME}.",
            "Hope your day is going well.",
            "You're crushing it."
          ],
          evening: [
            "Good evening, ${FIRST_NAME}.",
            "Time to relax.",
            "You made it through the day."
          ]
        }
      }
    },
    {
      module: "newsfeed",
      position: "bottom_bar",
      config: {
        feeds: [
          {
            title: "Hacker News",
            url: "https://hnrss.org/frontpage"
          },
          {
            title: "NPR News",
            url: "https://feeds.npr.org/1001/rss.xml"
          }
        ],
        showSourceTitle: true,
        showPublishDate: true,
        broadcastNewsFeeds: true,
        broadcastNewsUpdates: true,
        updateInterval: 600000
      }
    },
    // Weather is pre-configured for ZIP 27615 (Raleigh, NC) using the free weathergov provider (US National Weather Service, no key needed).
    // For other locations or more features (icons, etc.), you can switch providers or add a free OpenWeatherMap key.
    // Example alternative (uncomment + add key):
    /*
    {
      module: "weather",
      position: "top_right",
      config: {
        weatherProvider: "openweathermap",
        type: "current",
        location: "Raleigh, NC",
        apiKey: "YOUR_API_KEY_HERE"
      }
    },
    */
    {
      module: "weather",
      position: "top_right",
      config: {
        weatherProvider: "weathergov",
        lat: 35.78,
        lon: -78.64,
        units: "imperial",
        updateInterval: 600000,
        showFeelsLike: true
      }
    },
    {
      module: "updatenotification",
      position: "top_bar",
      config: {
        updateInterval: 86400000
      }
    }
  ]
};

/*************** DO NOT EDIT BELOW THIS LINE ***************/
if (typeof module !== "undefined") { module.exports = config; }
CONFIGEOF

# Personalize the name in compliments (sed because the heredoc used literal)
sed -i "s/\${FIRST_NAME}/${FIRST_NAME}/g" config/config.js

ok "Config written with your name (${FIRST_NAME}) and working modules (no API keys required)"

# ─────────────────────────────────────────────────────────────────────────────
# 6. Create the launcher scripts (kiosk is default for Pi 2)
# ─────────────────────────────────────────────────────────────────────────────
step "6/8  Creating launchers and desktop integration"

cd "$TARGET_DIR"

# The kiosk launcher (recommended for Pi 2 — much lighter than Electron)
cat > start-mirror-kiosk.sh << 'LAUNCHER'
#!/bin/bash
# Magic Mirror Kiosk Launcher (browser) — optimized for Raspberry Pi 2 / low RAM
# Starts the MM server, then launches Chromium fullscreen on it.

set -e

MM_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$MM_DIR"

echo "🪞 Starting Magic Mirror (kiosk mode)..."

# Clean up any previous instances
pkill -f "MagicMirror" 2>/dev/null || true
pkill -f "chromium" 2>/dev/null || true
pkill -f "epiphany" 2>/dev/null || true
sleep 1

# Start the server in background (serveronly = no Electron)
npm run server > /tmp/magic-mirror-server.log 2>&1 &
SERVER_PID=$!

# Give the server a few seconds to bind :8080
for i in {1..12}; do
  if curl -s --max-time 1 http://127.0.0.1:8080 >/dev/null 2>&1; then
    break
  fi
  sleep 1
done

# Hide the mouse cursor after a few seconds of inactivity (very mirror-like)
unclutter -idle 2 -root >/dev/null 2>&1 || true

# Try to launch a good kiosk browser. Order matters for Pi OS variants.
BROWSER_CMD=""
if command -v chromium-browser >/dev/null 2>&1; then
  BROWSER_CMD="chromium-browser"
elif command -v chromium >/dev/null 2>&1; then
  BROWSER_CMD="chromium"
elif command -v epiphany-browser >/dev/null 2>&1; then
  BROWSER_CMD="epiphany-browser"
fi

if [ -z "$BROWSER_CMD" ]; then
  echo "No suitable kiosk browser found. Falling back to xdg-open (you may need to fullscreen manually)."
  xdg-open http://127.0.0.1:8080 &
else
  echo "Launching kiosk with $BROWSER_CMD ..."
  if [[ "$BROWSER_CMD" == *"chromium"* ]]; then
    "$BROWSER_CMD" \
      --kiosk \
      --incognito \
      --noerrdialogs \
      --disable-infobars \
      --disable-translate \
      --disable-features=Translate \
      --disable-pinch \
      --overscroll-history-navigation=0 \
      --app=http://127.0.0.1:8080 \
      >/tmp/magic-mirror-browser.log 2>&1 &
  else
    # Epiphany fallback
    "$BROWSER_CMD" --application-mode --profile /tmp/mm-kiosk http://127.0.0.1:8080 >/tmp/magic-mirror-browser.log 2>&1 &
  fi
fi

# When the browser exits, also stop the server (clean)
wait $SERVER_PID 2>/dev/null || true
echo "Magic Mirror stopped."
LAUNCHER

chmod +x start-mirror-kiosk.sh

# Also provide a tiny wrapper that users (or the .desktop) call
cat > start-mirror.sh << 'WRAPPER'
#!/bin/bash
# Simple entry point — launches the Pi 2 friendly kiosk by default.
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
exec "$DIR/start-mirror-kiosk.sh"
WRAPPER
chmod +x start-mirror.sh

ok "Launch scripts created"

# Desktop file (for double-click and autostart)
DESKTOP_FILE_CONTENT='[Desktop Entry]
Name=Magic Mirror
Comment=Your beautiful smart mirror display
Exec='"$TARGET_DIR"'/start-mirror.sh
Path='"$TARGET_DIR"'
Type=Application
Terminal=false
Categories=Utility;Application;
StartupNotify=false
X-GNOME-Autostart-enabled=true
'

# Put it on the actual Desktop (visible to user)
mkdir -p "${HOME_DIR}/Desktop"
echo "$DESKTOP_FILE_CONTENT" > "${HOME_DIR}/Desktop/Magic-Mirror.desktop"
chmod +x "${HOME_DIR}/Desktop/Magic-Mirror.desktop"

# Also enable auto-start on login (the magic "boot and it just shows the mirror" experience)
mkdir -p "${HOME_DIR}/.config/autostart"
echo "$DESKTOP_FILE_CONTENT" > "${HOME_DIR}/.config/autostart/Magic-Mirror.desktop"
chmod +x "${HOME_DIR}/.config/autostart/Magic-Mirror.desktop"

ok "Desktop icon + autostart entry created"

# ─────────────────────────────────────────────────────────────────────────────
# 7. Final permissions + small niceties
# ─────────────────────────────────────────────────────────────────────────────
step "7/8  Final touches"

# Make sure the whole tree is owned by the user (npm can leave root files sometimes)
sudo chown -R "${USER_NAME}:${USER_NAME}" "$TARGET_DIR" 2>/dev/null || true

# Small helper: a one-liner to stop everything cleanly
cat > "${HOME_DIR}/stop-mirror.sh" << 'STOP'
#!/bin/bash
pkill -f "MagicMirror" 2>/dev/null || true
pkill -f "chromium" 2>/dev/null || true
pkill -f "epiphany" 2>/dev/null || true
pkill -f "unclutter" 2>/dev/null || true
echo "Magic Mirror stopped."
STOP
chmod +x "${HOME_DIR}/stop-mirror.sh"

# Add a tiny README in the MM dir for when user explores
cat > "${TARGET_DIR}/PI2_README.txt" << 'PI2README'
Magic Mirror — Pi 2 Edition (installed via The Work Bench one-file installer)

QUICK COMMANDS
  Double-click the "Magic Mirror" icon on your Desktop.
  Or from terminal:   ~/MagicMirror/start-mirror.sh

TO STOP THE MIRROR (when in kiosk)
  - Press Alt+F4
  - Or from another computer on the same network: ssh pi@this-pi   then run:  ~/stop-mirror.sh
  - Or open a terminal on the Pi (Ctrl+Alt+T or right-click desktop) and run: ~/stop-mirror.sh

CUSTOMIZING WHAT YOU SEE
  Edit:   ~/MagicMirror/config/config.js
  Then restart the mirror (close kiosk, double-click icon again).

  Easy things to change:
  - Add your own calendar iCal URLs (Google Calendar → Settings → Integrate calendar → "Secret address in iCal format")
  - Weather is already on for 27615 (Raleigh). Edit the weather module in config.js for other locations or providers.
  - Change compliments, news feeds, clock format, etc.

  Full module list & docs: https://docs.magicmirror.builders/modules/introduction.html

TIPS FOR A REAL PHYSICAL MIRROR
  - Use a cheap HDMI monitor or old TV + HDMI cable
  - 2-way acrylic mirror sheet or mirror film on top of the screen (search "two way acrylic mirror")
  - A simple wood or 3D-printed frame
  - Power: good 5V/3A+ supply for the Pi (mirrors often run 24/7)
  - Optional: disable screen blanking in Pi OS settings or via raspi-config

TROUBLESHOOTING
  - Black screen? Wait 20 seconds after double-click. Server may still be starting.
  - Browser not found? The installer tried chromium-browser / chromium / epiphany.
  - Want the heavier Electron look instead of kiosk? Edit start-mirror-kiosk.sh or run:
      cd ~/MagicMirror && npm start
    (may be slow or OOM on a stock Pi 2)

This setup was tuned specifically for Raspberry Pi 2 hardware.
There is also a pure-web "Live" version at /magicmirror/live/ on this site — perfect for testing on an iPad or any browser. It includes the rolling 7-day Google Calendar, your own photo collections, local weather for 27615, 250 random fading quotes (here & now, youth, relaxing), and WhatsApp + SMS sync via the official web clients from your Google Android phone (tap "Sign in with Google" or the Messages button on the live page for easy setup instructions + direct access).

Enjoy your mirror!
PI2README

ok "Helpers and docs added"

# ─────────────────────────────────────────────────────────────────────────────
# 8. Launch for immediate gratification (the "it works!" moment)
# ─────────────────────────────────────────────────────────────────────────────
step "8/8  Almost done — launch preview?"

echo ""
echo -e "${GREEN}Installation complete!${RESET}"
echo ""
echo "What was installed:"
echo "  • MagicMirror² at ${TARGET_DIR}"
echo "  • Desktop icon: ~/Desktop/Magic-Mirror.desktop"
echo "  • Auto-starts on login (perfect for a dedicated mirror device)"
echo "  • Kiosk mode (lightweight browser — best for Pi 2 1 GB RAM)"
echo ""
echo -e "${BOLD}To launch later:${RESET} double-click the 'Magic Mirror' icon on your Desktop"
echo -e "${BOLD}To stop:${RESET}        Alt+F4 while in kiosk, or run: ~/stop-mirror.sh"
echo ""
echo "Config file: ${TARGET_DIR}/config/config.js"
echo "Edit it, then restart the mirror to see changes."
echo ""

read -r -p "Launch Magic Mirror right now so you can see it working? [Y/n] " launch_now
if [[ "$launch_now" =~ ^[Yy]$ ]] || [[ -z "$launch_now" ]]; then
  say "Launching in kiosk mode... (it may take 10-15 seconds to appear)"
  # Launch detached so the installer can finish cleanly
  nohup "${TARGET_DIR}/start-mirror-kiosk.sh" >/tmp/mm-launch.log 2>&1 &
  sleep 2
  echo ""
  echo -e "${GREEN}Magic Mirror should be starting in the background.${RESET}"
  echo "If you don't see it in ~15 seconds, open a terminal and run:"
  echo "   ~/MagicMirror/start-mirror.sh"
  echo ""
  echo "You can now close this terminal window."
else
  echo "Okay — launch it anytime from the Desktop icon."
fi

echo ""
echo -e "${CYAN}Thank you for using the Magic Mirror Pi 2 project from The Work Bench.${RESET}"
echo -e "${DIM}Web version for iPad / browser testing: /magicmirror/live/ (Google Calendar + Photos slideshow, touch-first)${RESET}"
echo -e "${DIM}https://your-workbench-site/magicmirror/${RESET}"
echo ""
exit 0
