#!/bin/sh
# Builds the app's offline time-zone database (doc/plan-a-context-precision.md §5) from pinned inputs, byte for byte
# the one in the app:
#
#   Tools/timezone/build_zonedb.sh [work directory] [output directory]
#
# Needs curl, unzip, shasum and clang (Xcode's command-line tools on a Mac). Run from the app's repository, the output
# goes to the app's resources; run on its own (as published), give the output directory.
#
# Inputs (each checked against its SHA-256 before use):
#   - timezone-boundary-builder 2026e, "with oceans", all zones (ODbL 1.0, from OpenStreetMap data)
#   - Natural Earth 10m admin 0 countries with lakes 5.1.1 (public domain): country names in the metadata
#   - ZoneDetect at 81ede727 (BSD-3-Clause): the builder and the format
#   - shapelib 1.6.3 (MIT option of LGPL-2.0-or-later OR MIT): reads the shapefiles for the builder
#
# Output: timezone21.bin, ZoneDetect format version 1, precision 21 (coordinates kept to about 20 m; the boundaries
# themselves are only as good as OpenStreetMap's). The build stops, writing nothing, unless the file's SHA-256 is
# EXPECTED below. The file and this script are published under the ODbL at
# https://sunapp24.com/apps/hallosunset/timezones/.
#
# Toolchains: the builder sorts its polygons with std::sort, whose order for equal keys is up to the C++ library, so it
# is patched to std::stable_sort (the shapefile's order then breaks ties), and floating-point contraction is off, so
# the result doesn't hang on how a compiler fuses multiply-adds. Verified to give EXPECTED with Apple clang 21 on
# arm64; on any other toolchain the output is accepted only if its SHA-256 is EXPECTED too.
set -eu

EXPECTED=cc8a2c5579cb6139010c8ba47600b733670c1fb69b555ece321842e8a3e7c59a

ROOT=$(cd "$(dirname "$0")/../.." && pwd)
WORK=${1:-$(mktemp -d)}
OUT=${2:-$ROOT/HalloSunset/HalloSunset/Resources/TimeZones}
mkdir -p "$WORK/download" "$WORK/src" "$OUT"
WORK=$(cd "$WORK" && pwd)
OUT=$(cd "$OUT" && pwd)
cd "$WORK"

fetch() { # url file sha256
    [ -f "download/$2" ] || curl -sSfL -o "download/$2" "$1"
    echo "$3  download/$2" | shasum -a 256 -c - >/dev/null || { echo "checksum mismatch: $2" >&2; exit 1; }
}

fetch https://github.com/evansiroky/timezone-boundary-builder/releases/download/2026e/timezones-with-oceans.shapefile.zip \
    timezones-with-oceans.shapefile.zip 150cdb3f28efa6fba39607bfe13ad54043741ced84639142a51769a437a686a1
fetch https://naciscdn.org/naturalearth/10m/cultural/ne_10m_admin_0_countries_lakes.zip \
    ne_10m_admin_0_countries_lakes.zip 3f1596b05b4a19bd97f3a54731497cffbb4dbed4cda494084e73dd6dd3d37264
fetch https://github.com/BertoldVdb/ZoneDetect/archive/81ede727f8771eda507150a95237cc8c518666d6.tar.gz \
    zonedetect.tar.gz ff31d90e30908e124d0bcce4b0e7317875bd7bee5255c3af626f13554c1a1bee
fetch https://github.com/OSGeo/shapelib/releases/download/v1.6.3/shapelib-1.6.3.tar.gz \
    shapelib-1.6.3.tar.gz 3ff5ead18ca6d2fe249f0e80b361e1ad6782165115268ed4a58c780a60c1e0eb

cd src
tar xzf ../download/shapelib-1.6.3.tar.gz
tar xzf ../download/zonedetect.tar.gz
mkdir -p tbb naturalearth
(cd tbb && unzip -oq ../../download/timezones-with-oceans.shapefile.zip)
(cd naturalearth && unzip -oq ../../download/ne_10m_admin_0_countries_lakes.zip)

SH=shapelib-1.6.3
ZD=ZoneDetect-81ede727f8771eda507150a95237cc8c518666d6
sed -i.orig 's/std::sort(polygons_.begin()/std::stable_sort(polygons_.begin()/' $ZD/database/builder/builder.cpp
grep -q 'std::stable_sort(polygons_.begin()' $ZD/database/builder/builder.cpp || { echo "builder patch failed" >&2; exit 1; }
CFLAGS="-O2 -ffp-contract=off"
clang $CFLAGS -c $SH/shpopen.c $SH/dbfopen.c $SH/safileio.c $SH/shptree.c $SH/sbnsearch.c -I$SH
ar rcs libshp.a shpopen.o dbfopen.o safileio.o shptree.o sbnsearch.o
clang++ $CFLAGS --std=c++11 $ZD/database/builder/builder.cpp -I$SH -L. -lshp -o builder

# The notice must stay under 256 bytes: longer strings are read as references.
NOTICE="Time zones: timezone-boundary-builder 2026e, from OpenStreetMap data (c) OpenStreetMap contributors, ODbL 1.0 https://opendatacommons.org/licenses/odbl/1-0/. Country names: Natural Earth, public domain."
./builder T tbb/combined-shapefile-with-oceans timezone21.bin 21 "$NOTICE" 1 >/dev/null
GOT=$(shasum -a 256 timezone21.bin | cut -d' ' -f1)
[ "$GOT" = "$EXPECTED" ] || { echo "timezone21.bin is $GOT, expected $EXPECTED: not copied" >&2; exit 1; }
cp timezone21.bin "$OUT/timezone21.bin"
echo "$GOT  $OUT/timezone21.bin"
