# =========================================================
# Variable
# =========================================================

# Framework
# Identity and metadata of framework. Human-readable name, machine-readable names(lower and upper), and semantic version.
FRAMEWORK_REGULAR=Framework Regular
FRAMEWORK_LOWER=frameworklower
FRAMEWORK_UPPER=FRAMEWORKUPPER
FRAMEWORK_VERSION=0.0.0

# Software
# Identity and metadata of software. Human-readable name, machine-readable names(lower and upper), and semantic version.
SOFTWARE_REGULAR=Software Regular
SOFTWARE_LOWER=softwarelower
SOFTWARE_UPPER=SOFTWAREUPPER
SOFTWARE_VERSION=0.0.0

# Go Module
# App module and import path used by go.mod and source imports. Valid Go module path.
GO_MODULE=go/module

# Directory
# Locations used by build and management commands. Relative or absolute paths.
SOURCE_DIR=./run/main
RELEASE_DIR=./release
FRAMEWORK_METADATA_DIR=./data/framework/metadata
SOFTWARE_METADATA_DIR=./data/software/metadata

# File
# Metadata file names without extension. File name only.
FRAMEWORK_METADATA_FLE=resource
SOFTWARE_METADATA_FLE=resource

# Derived Path
# Automatically generated from directory and file variables. Do not edit.
FRAMEWORK_METADATA_PATH=$(FRAMEWORK_METADATA_DIR)/$(FRAMEWORK_METADATA_FLE)
SOFTWARE_METADATA_PATH=$(SOFTWARE_METADATA_DIR)/$(SOFTWARE_METADATA_FLE)

# Target File Type
# File types scanned by update commands. Valid find expression.
TARGET_FILE_TYPE=\
	-name "*.go" \
	-o -name "*.json" \
	-o -name "*.yaml" \
	-o -name "*.yml"

# Go Module Placeholder
# Replacement rules applied by upd-gm-ph. Valid sed replacement expressions.
GO_MODULE_REPLACEMENT=\
	-e 's|gomodule|$(GO_MODULE)|g' \
	-e 's|go/module|$(GO_MODULE)|g' \
	-e 's|go-module|$(GO_MODULE)|g' \
	-e 's|go_module|$(GO_MODULE)|g'

# =========================================================
# Command
# =========================================================

# PHONY Target
.PHONY: \
	help \
	upd-gm-ph \
	upd-fw-md \
	upd-sw-md \
	go-ini \
	go-tid \
	go-stp \
	pre-rel \
	go-bld \
	go-bld-lin \
	go-bld-win \
	go-bld-mac \
	bld-lin-amd \
	bld-lin-arm \
	bld-win-amd \
	bld-win-arm \
	bld-mac-amd \
	bld-mac-arm

# Default Command
.DEFAULT_GOAL := help

# =========================================================
# Help
# =========================================================

help:
	@echo ""
	@echo "Available Commands:"
	@echo ""
	@printf "  %-18s %s\n" "upd-gm-ph"    "Update Go module placeholder"
	@printf "  %-18s %s\n" "upd-fw-md"    "Update framework metadata"
	@printf "  %-18s %s\n" "upd-sw-md"    "Update software metadata"
	@echo ""
	@printf "  %-18s %s\n" "go-ini"       "Initialize Go module"
	@printf "  %-18s %s\n" "go-tid"       "Tidy Go module dependencies"
	@printf "  %-18s %s\n" "go-stp"       "Initialize Go module and tidy dependencies"
	@echo ""
	@printf "  %-18s %s\n" "go-bld"       "Build all platform binaries"
	@printf "  %-18s %s\n" "go-bld-lin"   "Build all Linux binaries"
	@printf "  %-18s %s\n" "go-bld-win"   "Build all Windows binaries"
	@printf "  %-18s %s\n" "go-bld-mac"   "Build all macOS binaries"
	@echo ""
	@printf "  %-18s %s\n" "bld-lin-amd"  "Build Linux AMD64 binary"
	@printf "  %-18s %s\n" "bld-lin-arm"  "Build Linux ARM64 binary"
	@echo ""
	@printf "  %-18s %s\n" "bld-win-amd"  "Build Windows AMD64 binary"
	@printf "  %-18s %s\n" "bld-win-arm"  "Build Windows ARM64 binary"
	@echo ""
	@printf "  %-18s %s\n" "bld-mac-amd"  "Build macOS AMD64 binary"
	@printf "  %-18s %s\n" "bld-mac-arm"  "Build macOS ARM64 binary"
	@echo ""

# =========================================================
# Update
# =========================================================

upd-gm-ph:

	@find . -type f \
	\( $(TARGET_FILE_TYPE) \) \
	-exec sed -i \
		$(GO_MODULE_REPLACEMENT) \
		{} +

	@if [ -f go.mod ]; then \
		sed -i \
			$(GO_MODULE_REPLACEMENT) \
			go.mod; \
	fi

	@go mod tidy

	@echo "Go Module Updated!"

upd-fw-md:

	@jq \
		--arg framework_regular "$(FRAMEWORK_REGULAR)" \
		--arg framework_lower "$(FRAMEWORK_LOWER)" \
		--arg framework_upper "$(FRAMEWORK_UPPER)" \
		--arg framework_version "$(FRAMEWORK_VERSION)" \
		'.framework.regular=$$framework_regular|.framework.lower=$$framework_lower|.framework.upper=$$framework_upper|.framework.version=$$framework_version' \
		$(FRAMEWORK_METADATA_PATH).json \
		> $(FRAMEWORK_METADATA_PATH).json.tmp

	@mv $(FRAMEWORK_METADATA_PATH).json.tmp $(FRAMEWORK_METADATA_PATH).json

	@echo "Framework Metadata Updated!"

upd-sw-md:

	@jq \
		--arg software_regular "$(SOFTWARE_REGULAR)" \
		--arg software_lower "$(SOFTWARE_LOWER)" \
		--arg software_upper "$(SOFTWARE_UPPER)" \
		--arg software_version "$(SOFTWARE_VERSION)" \
		'.software.regular=$$software_regular|.software.lower=$$software_lower|.software.upper=$$software_upper|.software.version=$$software_version' \
		$(SOFTWARE_METADATA_PATH).json \
		> $(SOFTWARE_METADATA_PATH).json.tmp

	@mv $(SOFTWARE_METADATA_PATH).json.tmp $(SOFTWARE_METADATA_PATH).json

	@echo "Software Metadata Updated!"

# =========================================================
# Release
# =========================================================

pre-rel:
	@test -n "$(RELEASE_DIR)"
	@mkdir -p "$(RELEASE_DIR)"
	@find "$(RELEASE_DIR)" -mindepth 1 -delete

# =========================================================
# Initialize
# =========================================================

go-ini:
	@test -f go.mod || go mod init $(GO_MODULE)

go-tid:
	go mod tidy

go-stp: \
	go-ini \
	go-tid

# =========================================================
# Build Group
# =========================================================

go-bld: \
	pre-rel \
	go-tid \
	bld-lin-amd \
	bld-lin-arm \
	bld-win-amd \
	bld-win-arm \
	bld-mac-amd \
	bld-mac-arm

go-bld-lin: \
	pre-rel \
	go-tid \
	bld-lin-amd \
	bld-lin-arm

go-bld-win: \
	pre-rel \
	go-tid \
	bld-win-amd \
	bld-win-arm

go-bld-mac: \
	pre-rel \
	go-tid \
	bld-mac-amd \
	bld-mac-arm

# =========================================================
# Build Target
# =========================================================

# Linux AMD64
bld-lin-amd:
	CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
	go build \
	-trimpath \
	-buildvcs=false \
	-ldflags="-s -w" \
	-o $(RELEASE_DIR)/$(SOFTWARE_LOWER)-v$(SOFTWARE_VERSION)-linux-amd64 \
	$(SOURCE_DIR)

# Linux ARM64
bld-lin-arm:
	CGO_ENABLED=0 GOOS=linux GOARCH=arm64 \
	go build \
	-trimpath \
	-buildvcs=false \
	-ldflags="-s -w" \
	-o $(RELEASE_DIR)/$(SOFTWARE_LOWER)-v$(SOFTWARE_VERSION)-linux-arm64 \
	$(SOURCE_DIR)

# Windows AMD64
bld-win-amd:
	CGO_ENABLED=0 GOOS=windows GOARCH=amd64 \
	go build \
	-trimpath \
	-buildvcs=false \
	-ldflags="-s -w" \
	-o $(RELEASE_DIR)/$(SOFTWARE_LOWER)-v$(SOFTWARE_VERSION)-windows-amd64.exe \
	$(SOURCE_DIR)

# Windows ARM64
bld-win-arm:
	CGO_ENABLED=0 GOOS=windows GOARCH=arm64 \
	go build \
	-trimpath \
	-buildvcs=false \
	-ldflags="-s -w" \
	-o $(RELEASE_DIR)/$(SOFTWARE_LOWER)-v$(SOFTWARE_VERSION)-windows-arm64.exe \
	$(SOURCE_DIR)

# macOS AMD64
bld-mac-amd:
	CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 \
	go build \
	-trimpath \
	-buildvcs=false \
	-ldflags="-s -w" \
	-o $(RELEASE_DIR)/$(SOFTWARE_LOWER)-v$(SOFTWARE_VERSION)-macos-amd64 \
	$(SOURCE_DIR)

# macOS ARM64
bld-mac-arm:
	CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 \
	go build \
	-trimpath \
	-buildvcs=false \
	-ldflags="-s -w" \
	-o $(RELEASE_DIR)/$(SOFTWARE_LOWER)-v$(SOFTWARE_VERSION)-macos-arm64 \
	$(SOURCE_DIR)