#   Zerocat Mini Machine --- A word processing machine of supreme integrity.
#
#   Copyright (C) 2022, 2023, 2025  Kai Mertens <kmx@posteo.net>
#
#   This file is part of Zerocat Mini Machine.
#
#   Zerocat Mini Machine is free software: you can redistribute it
#   and/or modify it under the terms of the GNU General Public License as
#   published by the Free Software Foundation, either version 3 of the
#   License, or (at your option) any later version.
#
#   Zerocat Mini Machine is distributed in the hope that it will be
#   useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#   General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with Zerocat Mini Machine.
#   If not, see <http://www.gnu.org/licenses/>.


#   Initial Guix Channel
#   ====================
#
#   This make file has been tested on GNU Guix System,
#   generated from channel guix ‘6992e66b21’:
#
#   guix describe -f channels
#   --------------------------------------------------------------------------
#   (list (channel
#           (name 'guix)
#           (url "https://git.savannah.gnu.org/git/guix.git")
#           (branch "master")
#           (commit
#             "266a713ae3ac742258ff11b6edd966288177d9e9")
#           (introduction
#             (make-channel-introduction
#               "9edb3f66fd807b096b48283debdcddccfea34bad"
#               (openpgp-fingerprint
#                 "BBB0 2DDF 2CEA F6A8 0D1D  E643 A2A0 6DF2 A33A 54FA")))))


#   Usage
#   =====
#
#   To get an overview of targets, type:
#
#           make -C ../guix help


#   Workaround for GNU Make < 4.3
#   =============================
#
#   Finalize commands within a $(shell) function with semicolon, e.g.:
#
#           $(shell echo;)


# Shell
SHELL                         := /bin/sh


# White Space
EMPTY                         :=
SPACE                         := $(EMPTY) $(EMPTY)
COMMA                         := ,
M5                            := xxxxx
TAB1                          := $(SPACE)$(SPACE)$(SPACE)$(SPACE)


# Root Paths
ROOT                          := ../
ROOT_DOC                      := ../doc/
ROOT_GUIX                     := ../guix/
ROOT_HARDWARE                 := ../hardware/


# Utilities
LS                            := $(shell command -v ls;)
LS_FLAGS                      :=
$(if $(strip $(LS)),,         $(error Cannot find ls utility))

ECHO                          := $(shell command -v echo;)
ECHO_FLAGS                    :=
$(if $(strip $(ECHO)),,       $(error Cannot find echo utility))

#    Do not err out, use warning instead.
GUIX                          := $(shell command -v guix;)
GUIX_FLAGS                    :=
$(if $(strip $(GUIX)),,       $(warning Cannot find guix utility))


# Files
GUIX_CHANNELS                 := $(ROOT_GUIX)channels.scm
GUIX_MANIFEST                 := $(ROOT_GUIX)manifest.scm


# Settings
PROJECT_TITLE                 := Zerocat Mini Machine
PROJECT_BRIEF                 := A word processing machine of supreme integrity.
MAKEFILE_TITLE                := Environment Setup with Guix
ISENV                         = $(shell $(ECHO) $(ECHO_FLAGS) "$${GUIX_ENVIRONMENT}";)


# Canned Rules
define HEADER                 =
$(strip\
	$(ECHO) $(ECHO_FLAGS)    ""\
	&& $(ECHO) $(ECHO_FLAGS) "$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)"\
	&& $(ECHO) $(ECHO_FLAGS) "$(M5) $(PROJECT_TITLE)"\
	&& $(ECHO) $(ECHO_FLAGS) "$(M5) – $(PROJECT_BRIEF)"\
	&& $(ECHO) $(ECHO_FLAGS) "$(M5) $(MAKEFILE_TITLE)"\
	&& $(ECHO) $(ECHO_FLAGS) "$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)$(M5)"\
)
endef
define HEADLINE               =
$(strip\
	$(ECHO) $(ECHO_FLAGS)    "$(M5) Process target “$(@)” $(M5)$(M5)"\
)
endef
define DONE                   =
$(strip\
	$(ECHO) $(ECHO_FLAGS)    "... end of target “$@”."\
	&& $(ECHO) $(ECHO_FLAGS) ""\
)
endef


# Suffixes, to be checked for old fashioned suffix rules
.SUFFIXES :


# Intermediate Targets
#~ .INTERMEDIATE :


# Secondary Targets
#~ .SECONDARY :                  # Uncomment for debugging


# Phony Targets
.PHONY :\
	default\
	\
	hello\
	help\
	usage\
	\
	pull\
	environment\
	checkout\
	shell\
	\
	go\
	clean-go


# Targets
#   default target
default : help
	@$(HEADLINE)\
	&& $(DONE);

#   display greeting
#     provided with usage, clean and help
hello :
	@$(HEADER)\
	&& $(DONE);

#   display help information
help : hello
	@$(HEADLINE)\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "List of Targets"\
	&& $(ECHO) $(ECHO_FLAGS) "==============="\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "Default"\
	&& $(ECHO) $(ECHO_FLAGS) "-------"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "default"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)same as help"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "Help"\
	&& $(ECHO) $(ECHO_FLAGS) "----"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "hello"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)greeter, provided with targets usage and help"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)greeter, provided with targets pull, environment"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)greeter, provided with targets go, clean-go"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "help"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)list available targets"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "usage"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)get environment status and usage information"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "Actions"\
	&& $(ECHO) $(ECHO_FLAGS) "-------"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "pull"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)create profile generation, if not any"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "go"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)create environment on the fly and compile documentation"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "Environments"\
	&& $(ECHO) $(ECHO_FLAGS) "------------"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "To get help, run ‘make -C $(ROOT_GUIX) usage’."\
	&& $(ECHO) $(ECHO_FLAGS) "To leave an environment when you are done, type ‘exit’."\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "checkout"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)checkout current profile generation, instantiate channels"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)The “checkout” environment can be used to run project’s guix command,"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)e.g. to search for packages of project’s channels."\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)Goals pull, environment, go, clean-go are disabled."\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "shell"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)create a pure shell environment with nothing but prerequisites set up"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)This goal is available on “checkout” environment."\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)Goals pull, environment, go, clean-go are disabled."\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "environment"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)checkout current profile generation, instantiate channels, create a pure shell environment"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)Goals pull, environment, go, clean-go are disabled."\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "Clean"\
	&& $(ECHO) $(ECHO_FLAGS) "-----"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "clean-go"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)create environment on the fly and remove compiled documentation"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(DONE);

#   usage: report environment status and usage information
usage : hello
	@$(HEADLINE)\
	&& if [ -z "$${GUIX_ENVIRONMENT}" ]\
		; then\
			$(ECHO) $(ECHO_FLAGS) "Initial Environment."\
			&& if [ -z "$(GUIX)" ]\
				; then\
					$(ECHO) $(ECHO_FLAGS)    "Command ‘guix’ is not available."\
					&& $(ECHO) $(ECHO_FLAGS) "Install GNU Guix Package Manager, or run GNU Guix System."\
				; else\
					$(ECHO) $(ECHO_FLAGS)    "Command ‘guix’ is available."\
					&& $(ECHO) $(ECHO_FLAGS) "Run ‘make -C $(ROOT_GUIX) pull’ to create a guix profile, if not any."\
					&& $(ECHO) $(ECHO_FLAGS) "Run ‘make -C $(ROOT_GUIX) checkout’ to instantiate current profile."\
					&& $(ECHO) $(ECHO_FLAGS) "Run ‘make -C $(ROOT_GUIX) environment’ to instantiate current profile and to create a pure shell environment."\
					&& $(ECHO) $(ECHO_FLAGS) "Run ‘make -C $(ROOT_GUIX) help’ to see more options."\
				; fi\
		; else\
			declare\
				-a arr=($$($(LS) $(LS_FLAGS) "$${GUIX_ENVIRONMENT}/bin"))\
			&& if [ $${#arr[@]} -lt 3 ]\
				; then\
					$(ECHO) $(ECHO_FLAGS)    "Checkout Environment, profile generation instantiated."\
					&& $(ECHO) $(ECHO_FLAGS) "Run ‘guix search PATTERN’ to search for packages."\
					&& $(ECHO) $(ECHO_FLAGS) "Run ‘make -C $(ROOT_GUIX) shell’ to set up prerequisites."\
					&& $(ECHO) $(ECHO_FLAGS) "Run ‘exit’ to restore initial environment."\
					&& $(ECHO) $(ECHO_FLAGS) "Run ‘make -C $(ROOT_GUIX) help’ to see more options."\
				; else\
					$(ECHO) $(ECHO_FLAGS) "Shell Environment, prerequisites set up."\
					&& if [ -z "$$LANG" ]\
						; then\
							$(ECHO) $(ECHO_FLAGS)    "Run ‘export LANG=en_US.utf8’ to adjust terminal output,"\
							&& $(ECHO) $(ECHO_FLAGS) "  adapt language/country code to your needs."\
						; fi\
					&& $(ECHO) $(ECHO_FLAGS) "Run ‘exit’ to leave environment."\
				; fi\
		; fi\
	&& $(DONE);


#   start of conditional block
ifeq ($(strip $(ISENV)),)


##   create profile and profile generation (on GNU Guix System)
ifneq ($(strip $(GUIX)),)
pull : $(GUIX_CHANNELS) hello
	@$(HEADLINE)\
	&& $(GUIX) time-machine --channels=$<\
	&& $(DONE);
endif

##   checkout profile generation (on GNU Guix System)
ifneq ($(strip $(GUIX)),)
checkout : $(GUIX_CHANNELS)
	@$(HEADLINE)\
	&& $(GUIX) shell --profile=$$($(GUIX) time-machine --channels=$<)\
	&& $(DONE);
endif

##   set up pure environment, provide prerequisites in one go (on GNU Guix System)
ifneq ($(strip $(GUIX)),)
environment : $(GUIX_CHANNELS) $(GUIX_MANIFEST) hello
	@$(HEADLINE)\
	&& LANG=C\
	&& $(GUIX) time-machine --channels=$(GUIX_CHANNELS)\
		-- shell -q --pure --preserve=^LANG --rebuild-cache --manifest=$(GUIX_MANIFEST)\
	&& $(DONE);
endif

##   create guix environment on the fly, then compile all files
ifneq ($(strip $(GUIX)),)
go : $(GUIX_CHANNELS) $(GUIX_MANIFEST) hello
	@$(HEADLINE)\
	&& $(ECHO) $(ECHO_FLAGS) "\
			LANG=C\
			&& make -C $(ROOT_DOC)\
		"\
	| $(GUIX) time-machine --channels=$(GUIX_CHANNELS)\
		-- shell -q --pure --preserve=^LANG --rebuild-cache --manifest=$(GUIX_MANIFEST)\
	&& $(DONE);
endif

##   create guix environment on the fly, then remove all compiled files
ifneq ($(strip $(GUIX)),)
clean-go : $(GUIX_CHANNELS) $(GUIX_MANIFEST) hello
	@$(HEADLINE)\
	&& $(ECHO) $(ECHO_FLAGS) "\
			LANG=C\
			&& make -C $(ROOT_DOC) clean\
		"\
	| $(GUIX) time-machine --channels=$<\
		-- shell -q --pure --preserve=^LANG --rebuild-cache --manifest=$(GUIX_MANIFEST)\
	&& $(DONE);
endif


#   start of alternative block
else


##   set up shell within ‘checkout’ environment, thus using project’s profile generation
ifneq ($(strip $(GUIX)),)
shell : $(GUIX_MANIFEST)
	@$(HEADLINE)\
	&& if [ -n "$${GUIX_ENVIRONMENT}" ]\
		; then\
			declare\
				-a arr=($$($(LS) $(LS_FLAGS) "$${GUIX_ENVIRONMENT}/bin"))\
			&& if [ $${#arr[@]} -eq 2 ]\
				; then\
					$(ECHO) $(ECHO_FLAGS) "Run ‘make -C $(ROOT_GUIX) usage’ to get shell status."\
					&& "$${GUIX_ENVIRONMENT}/bin/guix"\
						shell -q --pure --preserve=^LANG --rebuild-cache --manifest=$<\
				; fi\
		; fi\
	&& $(DONE);
endif


#   end of conditional block
endif
