# Configuration
APP_ROOT := $(abspath $(lastword $(MAKEFILE_LIST))/..)
APP_NAME := emu

WPS_URL = http://localhost:5000

# Used in target refresh-notebooks to make it looks like the notebooks have
# been refreshed from the production server below instead of from the local dev
# instance so the notebooks can also be used as tutorial notebooks.
OUTPUT_URL = https://pavics.ouranos.ca/wpsoutputs/emu

SANITIZE_FILE := https://github.com/Ouranosinc/PAVICS-e2e-workflow-tests/raw/master/notebooks/output-sanitize.cfg

# Bumpversion 'dry' config
# if 'dry' is specified as target, any bumpversion call using 'BUMP_XARGS' will not apply changes
BUMP_XARGS ?= --verbose --allow-dirty
ifeq ($(filter dry, $(MAKECMDGOALS)), dry)
	BUMP_XARGS := $(BUMP_XARGS) --dry-run
endif
.PHONY: dry
dry: setup.cfg
	@-echo > /dev/null

# end of configuration

define PRINT_HELP_PYSCRIPT
import re, sys

for line in sys.stdin:
	match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line)
	if match:
		target, help = match.groups()
		print("%-20s %s" % (target, help))
	else:
		match = re.match(r'^## (.*)$$', line)
		if match:
			help = match.groups()[0]
			print("\n%s" % (help))
endef
export PRINT_HELP_PYSCRIPT

BROWSER := python -c "$$BROWSER_PYSCRIPT"

.DEFAULT_GOAL := help

help: ## print this help message. (Default)
	@echo "Please use 'make <target>' where <target> is one of:"
	@python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST)

## Service targets:

start: ## start emu service as daemon (background process)
	@echo "Starting application ..."
	@-bash -c "$(APP_NAME) start -d"

stop: ## stop emu service
	@echo "Stopping application ..."
	@-bash -c "$(APP_NAME) stop"

restart: stop start  ## restart emu service
	@echo "Restarting application ..."

status: ## show status of emu service
	@echo "Showing status ..."
	@-bash -c "$(APP_NAME) status"

## Build targets:

install: ## install emu application
	@echo "Installing application ..."
	@-bash -c 'pip install -e .'
	@echo "\nStart service with \`make start\` and stop with \`make stop\`."

develop: install-dev ## install emu application with development libraries
	@python -m pip install .
	@-bash -c 'prek install'

debug:
	@-echo "Following variables are used:"
	@-echo "  SHELL:                         $(SHELL)"
	@-echo "  APP_ROOT:                      $(APP_ROOT)"
	@-echo "  BUMP_XARGS:                    $(BUMP_XARGS)"

clean-build: ## remove build artifacts
	@echo "Removing build artifacts ..."
	@-rm -fr build/
	@-rm -fr dist/
	@-rm -fr .eggs/
	@-find . -name '*.egg-info' -exec rm -fr {} +
	@-find . -name '*.egg' -exec rm -f {} +
	@-find . -name '*.log' -exec rm -fr {} +
	@-find . -name '*.sqlite' -exec rm -fr {} +

clean-pyc: ## remove Python file artifacts
	@echo "Removing Python file artifacts ..."
	@-find . -name '*.pyc' -exec rm -f {} +
	@-find . -name '*.pyo' -exec rm -f {} +
	@-find . -name '*~' -exec rm -f {} +
	@-find . -name '__pycache__' -exec rm -fr {} +

clean-test: ## remove test and coverage artifacts
	@echo "Removing test artifacts ..."
	@-rm -fr .tox/
	@-rm -f .coverage
	@-rm -fr .pytest_cache

clean-dist: clean  ## remove git ignored files and directories
	@echo "Running 'git clean' ..."
	@git diff --quiet HEAD || echo "There are uncommitted changes! Aborting 'git clean' ..."
	## do not use git clean -e/--exclude here, add them to .gitignore instead
	@-git clean -dfx

clean-docs: ## remove documentation artifacts
	@echo "Removing documentation artifacts ..."
	@-rm -f docs/emu.rst
	@-rm -f docs/modules.rst
	$(MAKE) -C docs clean

install-dev:
	@echo "Installing development requirements for tests and docs ..."
	@python -m pip install --group dev

install-lint: ## install dependencies needed for linting
	@python -m pip install --quiet --group lint

install-docs: ## install dependencies needed for building the docs
	@python -m pip install --quiet --group docs

install-test: ## install dependencies needed for standard testing
	@python -m pip install --quiet --group test

install-tox: ## install base dependencies needed for running tox
	@python -m pip install --quiet --group tox

lint: install-lint ## check style
	@echo "Running flake8 code style checks ..."
	@bash -c 'ruff check src/emu tests'

## Testing targets:

test: install-test ## run offline and fast tests quickly with the default Python
	@echo "Running tests (skip slow and online tests) ..."
	@bash -c 'pytest -v -m "not slow and not online" tests/'

test-tox: install-tox ## run tests on every available Python version with tox
	@bash -c 'tox'

test-all: ## run all tests quickly with the default Python
	@echo "Running all tests (including slow and online tests) ..."
	@bash -c 'pytest -v'

test-notebooks: notebook-sanitizer
	@echo "Running notebook-based tests"
	@bash -c "env WPS_URL=$(WPS_URL) pytest --nbval --verbose $(CURDIR)/docs/source/notebooks/ --sanitize-with $(CURDIR)/docs/source/output-sanitize.cfg --ignore $(CURDIR)/docs/source/notebooks/.ipynb_checkpoints"

test-notebooks-lax: notebook-sanitizer ## run tests on notebooks but don't be so strict about outputs
	@echo "Running notebook-based tests"
	@bash -c "env WPS_URL=$(WPS_URL) pytest --nbval-lax --rootdir tests/ --verbose $(CURDIR)/docs/source/notebooks/ --ignore $(CURDIR)/docs/source/notebooks/.ipynb_checkpoints"

coverage: ## check code coverage quickly with the default Python
	@bash -c 'coverage run --source emu -m pytest'
	@bash -c 'coverage report -m'
	@bash -c 'coverage html'
	$(BROWSER) htmlcov/index.html

## Sphinx targets:

autodoc: install-docs clean-docs ## create sphinx-apidoc files:
	@bash -c 'sphinx-apidoc -o docs/source/apidoc --private --module-first src/emu'

build-docs: autodoc ## generate Sphinx HTML documentation, including API docs
	@echo "Generating docs with Sphinx ..."
	$(MAKE) -C docs html

docs: build-docs ## generate Sphinx HTML documentation, including API docs
	@echo "Open your browser to: file:/$(APP_ROOT)/docs/build/html/index.html"
	## do not execute xdg-open automatically since it hangs ReadTheDocs and job does not complete
	@echo "xdg-open $(APP_ROOT)/docs/build/html/index.html"
ifndef READTHEDOCS
	$(BROWSER) docs/_build/html/index.html
endif

servedocs: docs ## compile the docs watching for changes
	@echo "Compiling the docs and watching for changes ..."
	$(MAKE) -C docs livehtml

notebook-sanitizer: ## sanitize notebooks with configuration file
	@echo "Copying notebook output sanitizer ..."
	@-bash -c "curl -L $(SANITIZE_FILE) -o $(CURDIR)/docs/source/output-sanitize.cfg --silent"

refresh-notebooks: ## refreshing all notebook outputs under docs/source/notebooks
	@echo "Refresh all notebook outputs under docs/source/notebooks"
	@bash -c 'for nb in $(CURDIR)/docs/source/notebooks/*.ipynb; do WPS_URL="$(WPS_URL)" jupyter nbconvert --to notebook --execute --ExecutePreprocessor.timeout=60 --output "$$nb" "$$nb"; sed -i "s@$(WPS_URL)/outputs/@$(OUTPUT_URL)/@g" "$$nb"; done; cd $(APP_ROOT)'

## Deployment targets:

bump: ## bump the version string
	@-echo "Updating package version ..."
	@[ "${VERSION}" ] || ( echo ">> 'VERSION' is not set"; exit 1 )
	@-bash -c 'bump-my-version bump $(BUMP_XARGS) --new-version "${VERSION}" patch;'

dist: clean ## build source and wheel package
	@python -m flit build
	@bash -c 'ls -l dist/'

release: dist ## upload source and wheel packages
	@echo "Uploading source and wheel packages ..."
	@python -m flit publish dist/*
