#!/usr/bin/env bash

# Usage: ./fetch_superchain_config.sh
# Switch to the same directory as the script and run it.
# This will checkout the latest superchain registry commit and create three files.
# - superchain-configs.tar: A tar archive containing all superchain configs
# - ../src/superchain/chain_specs.rs: A Rust file containing all chain specs

# Requires:
# - MacOS: brew install qpdf zstd yq

SCRIPT_DIR=$(pwd)
TEMP_DIR=$(mktemp -d)

# Clone the repository and go to the directory
git clone --depth 1 https://github.com/ethereum-optimism/superchain-registry.git "$TEMP_DIR"
# shellcheck disable=SC2164
cd "$TEMP_DIR"


DICT_FILE="$TEMP_DIR/superchain/extra/dictionary"
TARGET_PATH="$TEMP_DIR/result"
GENESIS_TARGET_PATH="$TARGET_PATH/genesis"
CONFIGS_TARGET_PATH="$TARGET_PATH/configs"

GENESIS_SRC_DIR="$TEMP_DIR/superchain/extra/genesis"
CONFIGS_SRC_DIR="$TEMP_DIR/superchain/configs"
mkdir -p "$GENESIS_TARGET_PATH"
mkdir -p "$CONFIGS_TARGET_PATH"

echo "Convert TOML files to JSON..."
# JSON makes the handling in no-std environments easier
find "$CONFIGS_SRC_DIR" -type f -name "*.toml" | while read -r file; do

    # Compute destination file path
    REL_PATH="${file#"$CONFIGS_SRC_DIR"/}"
    DEST_PATH="$CONFIGS_TARGET_PATH/${REL_PATH%.toml}"

    # Ensure destination directory exists
    mkdir -p "$(dirname "$DEST_PATH")"

    # Convert the toml file to json
    yq -p toml -o json "$file" > "$DEST_PATH.json"
done

echo "Extract and compress the genesis files..."
# We compress the genesis files with zlib-flate to save space and to a compression
# format that makes it easier to handle them in no-std environments
find "$GENESIS_SRC_DIR" -type f -name "*.json.zst" | while read -r file; do

    # Compute destination file path
    REL_PATH="${file#"$GENESIS_SRC_DIR"/}"
    DEST_PATH="$GENESIS_TARGET_PATH/${REL_PATH%.zst}"

    # Ensure destination directory exists
    mkdir -p "$(dirname "$DEST_PATH")"

    # Extract the file
    zstd -q -d -D="$DICT_FILE" "$file" -o "$DEST_PATH"

    # Remove "config" field from genesis files, because it is not consistent populated.
    # We will add it back in from the chain config file during runtime.
    # See: https://github.com/ethereum-optimism/superchain-registry/issues/901
    jq -c 'del(.config)' "$DEST_PATH" > "$DEST_PATH.tmp"
    mv "$DEST_PATH.tmp" "$DEST_PATH"

    # Compress with zlib-flate and remove the original file
    zlib-flate -compress < "$DEST_PATH" > "$DEST_PATH.zz"
    rm "$DEST_PATH"

done

# Save revision
git rev-parse HEAD > "$TARGET_PATH/superchain_registry_commit"
git rev-parse HEAD > "$SCRIPT_DIR/superchain_registry_commit"

# Copy the LICENSE file
cp "$TEMP_DIR/LICENSE" "$TARGET_PATH/LICENSE"

# Set the modification time of all files to 1980-01-01 to ensure the archive is deterministic
find "$TARGET_PATH" -exec touch -t 198001010000.00 {} +

# shellcheck disable=SC2164
cd "$TARGET_PATH"
# Create a tar archive excluding files that are not relevant superchain directory
# shellcheck disable=SC2035
COPYFILE_DISABLE=1 tar --no-acls --no-xattrs -cf superchain-configs.tar --exclude "._COMMIT" *

# Move result to the script directory
mv superchain-configs.tar "$SCRIPT_DIR"

echo "Get chain name and identifiers from chainList.json"
# shellcheck disable=SC2002
JSON_DATA=$(cat "$TEMP_DIR/chainList.json" | jq -r 'sort_by(.parent.chain, .identifier | split("/")[1])')

# Extract network and chain names
PARENT_CHAINS=$(echo "$JSON_DATA" | jq -r '.[].parent.chain')
IDENTIFIERS=$(echo "$JSON_DATA" | jq -r '.[].identifier | split("/")[1]')
# shellcheck disable=SC2206
PARENT_CHAINS_ARRAY=($PARENT_CHAINS)
# shellcheck disable=SC2206
IDENTIFIERS_ARRAY=($IDENTIFIERS)

RESULTS=()
RESULT_RS="// Generated by fetch_superchain_config.sh\nuse crate::create_superchain_specs;\n"
ENUM_RS=""

echo "Generate chain_specs.rs..."
for i in "${!PARENT_CHAINS_ARRAY[@]}"; do
  NAME="${IDENTIFIERS_ARRAY[$i]}"
  ENVIRONMENT="${PARENT_CHAINS_ARRAY[$i]}"
  # Skip Optimism and Base here because it is implemented separately
  if [ "$NAME" == "op" ] || [ "$NAME" == "base" ]; then
     continue
  fi

  # Validate file existence in our target path <environment>/<name>.json.zst
  FILE_PATH="$GENESIS_TARGET_PATH/$ENVIRONMENT/$NAME.json.zz"
  if [ -f "$FILE_PATH" ]; then
    RESULTS+=("{\"name\": \"$NAME\", \"environment\": \"$ENVIRONMENT\"}")
    ENUM_RS+="    (\"$NAME\", \"$ENVIRONMENT\"),\n"
  else
    echo "Error: File not found: $FILE_PATH" >&2
  fi
done


# Write chain_specs.rs
echo -e "$RESULT_RS" > "$SCRIPT_DIR/../src/superchain/chain_specs.rs"

# Append the enum creation to chain_specs.rs
echo -e "create_superchain_specs!(\n${ENUM_RS});" \
  >> "$SCRIPT_DIR/../src/superchain/chain_specs.rs"

# Clean up
# shellcheck disable=SC2164
cd "$TEMP_DIR/../"
rm -rf "$TEMP_DIR"

echo "Done."
