.DEFAULT_GOAL := all

PYTHON := python3

VENV_DIR := .venv
VENV_PYTHON := $(VENV_DIR)/bin/python
VENV_PIP := $(VENV_PYTHON) -m pip

ROOT := ..
TEST_DIR := tests
APP := main.py
STDDEV_APP := profiling/stddev.py
GEN_DATA_APP := profiling/gen_data.py
REQ_FILE := requirements.txt
SYSTEM_PACKAGES := python3 python3-venv python3-pip python3-tk doxygen graphviz zip desktop-file-utils

TEAM_DIR := xkrepij00_xmatejv00_xsvacia00
PACK_NAME := $(TEAM_DIR).zip
PACK_OUTPUT := $(ROOT)/$(PACK_NAME)

BUILD_DIR := $(ROOT)/build
PROFILING_DIR := $(ROOT)/profiling
INSTALL_SRC := $(BUILD_DIR)/install
DEB_BUILD_DIR := $(BUILD_DIR)/deb

DOC_SRC := $(ROOT)/doc/html

VERSION ?= 1.0.0
DEB_ARCH := all

LINUX_DEPLOY_DIR := $(ROOT)/deploy/linux
CALC_PKG := ivs-calc
STDDEV_PKG := ivs-stddev
CALC_DEB := $(INSTALL_SRC)/$(CALC_PKG)_$(VERSION).deb
STDDEV_DEB := $(INSTALL_SRC)/$(STDDEV_PKG)_$(VERSION).deb

CALC_BUILD_DIR := $(DEB_BUILD_DIR)/$(CALC_PKG)
STDDEV_BUILD_DIR := $(DEB_BUILD_DIR)/$(STDDEV_PKG)

.PHONY: all deps deps-system deps-python venv-reset run stddev test doc installers pack clean help

all: deps
	@echo "Project is ready."

deps: deps-system deps-python

deps-system:
	@echo "Checking required Ubuntu system packages..."
	@missing="$$(for pkg in $(SYSTEM_PACKAGES); do \
		dpkg-query -W -f='$${Status}' $$pkg 2>/dev/null | grep -q 'install ok installed' || echo $$pkg; \
	done)"; \
	if [ -n "$$missing" ]; then \
		echo "Installing missing system packages: $$missing"; \
		sudo apt-get update; \
		sudo apt-get install -y $$missing; \
	else \
		echo "All required system packages are already installed."; \
	fi
	@$(PYTHON) -c "import tkinter; print('Tkinter OK, Tk version:', tkinter.TkVersion)"

deps-python:
	@if [ ! -x "$(VENV_PYTHON)" ]; then \
		echo "Creating virtual environment in $(VENV_DIR)..."; \
		$(PYTHON) -m venv "$(VENV_DIR)"; \
	fi
	@$(VENV_PIP) install --upgrade pip
	@if [ -f $(REQ_FILE) ]; then \
		$(VENV_PIP) install -r $(REQ_FILE); \
	else \
		echo "$(REQ_FILE) not found, nothing to install."; \
	fi

venv-reset:
	rm -rf "$(VENV_DIR)"
	$(MAKE) deps-python

run: deps
	"$(VENV_PYTHON)" $(APP)

stddev: deps
	mkdir -p $(PROFILING_DIR)
	"$(VENV_PYTHON)" $(GEN_DATA_APP) 10 | "$(VENV_PYTHON)" -m cProfile -o $(PROFILING_DIR)/vystup_10.prof $(STDDEV_APP)
	"$(VENV_PYTHON)" -c "import pstats; s=pstats.Stats('$(PROFILING_DIR)/vystup_10.prof'); s.sort_stats('cumtime').print_stats()" > $(PROFILING_DIR)/vystup_10.txt
	"$(VENV_PYTHON)" $(GEN_DATA_APP) 1000 | "$(VENV_PYTHON)" -m cProfile -o $(PROFILING_DIR)/vystup_1000.prof $(STDDEV_APP)
	"$(VENV_PYTHON)" -c "import pstats; s=pstats.Stats('$(PROFILING_DIR)/vystup_1000.prof'); s.sort_stats('cumtime').print_stats()" > $(PROFILING_DIR)/vystup_1000.txt
	"$(VENV_PYTHON)" $(GEN_DATA_APP) 1000000 | "$(VENV_PYTHON)" -m cProfile -o $(PROFILING_DIR)/vystup_1000000.prof $(STDDEV_APP)
	"$(VENV_PYTHON)" -c "import pstats; s=pstats.Stats('$(PROFILING_DIR)/vystup_1000000.prof'); s.sort_stats('cumtime').print_stats()" > $(PROFILING_DIR)/vystup_1000000.txt
test: deps
	"$(VENV_PYTHON)" -m pytest $(TEST_DIR)

doc:
	doxygen Doxyfile

installers: clean-installers calculator-installer stddev-installer
	@echo "Created Linux installers:"
	@ls -lh "$(INSTALL_SRC)"/*.deb

calculator-installer:
	@echo "Building $(CALC_DEB)..."
	@install -d "$(CALC_BUILD_DIR)/DEBIAN"
	@install -d "$(CALC_BUILD_DIR)/opt/$(CALC_PKG)/src"
	@install -d "$(CALC_BUILD_DIR)/usr/bin"
	@install -d "$(CALC_BUILD_DIR)/usr/share/applications"
	@install -d "$(INSTALL_SRC)"
	@sed 's|__VERSION__|$(VERSION)|g' \
		"$(LINUX_DEPLOY_DIR)/calc/control.in" \
		> "$(CALC_BUILD_DIR)/DEBIAN/control"
	@install -m 755 "$(LINUX_DEPLOY_DIR)/calc/postinst" "$(CALC_BUILD_DIR)/DEBIAN/postinst"
	@install -m 755 "$(LINUX_DEPLOY_DIR)/calc/postrm" "$(CALC_BUILD_DIR)/DEBIAN/postrm"
	@install -m 644 "$(LINUX_DEPLOY_DIR)/calc/ivs-calc.desktop" "$(CALC_BUILD_DIR)/usr/share/applications/ivs-calc.desktop"
	@install -m 755 "$(LINUX_DEPLOY_DIR)/calc/ivs-calc" "$(CALC_BUILD_DIR)/opt/$(CALC_PKG)/ivs-calc"
	@install -m 755 "$(LINUX_DEPLOY_DIR)/calc/ivs-calc" "$(CALC_BUILD_DIR)/usr/bin/ivs-calc"
	@tar \
		--exclude='html' \
		--exclude='latex' \
		--exclude='.venv' \
		--exclude='.pytest_cache' \
		--exclude='*/.pytest_cache' \
		--exclude='__pycache__' \
		--exclude='*/__pycache__' \
		--exclude='*.pyc' \
		--exclude='*.pyo' \
		-C . -cf - . | tar -C "$(CALC_BUILD_DIR)/opt/$(CALC_PKG)/src" -xf -
	@find "$(CALC_BUILD_DIR)/opt/$(CALC_PKG)" -type d -exec chmod 755 {} \;
	@find "$(CALC_BUILD_DIR)/opt/$(CALC_PKG)" -type f -exec chmod 644 {} \;
	@chmod 755 "$(CALC_BUILD_DIR)/opt/$(CALC_PKG)/ivs-calc"
	@chmod 755 "$(CALC_BUILD_DIR)/usr/bin/ivs-calc"
	@chmod 755 "$(CALC_BUILD_DIR)/DEBIAN/postinst"
	@chmod 755 "$(CALC_BUILD_DIR)/DEBIAN/postrm"
	@dpkg-deb --root-owner-group -Zgzip --build "$(CALC_BUILD_DIR)" "$(CALC_DEB)"

stddev-installer:
	@echo "Building $(STDDEV_DEB)..."
	@install -d "$(STDDEV_BUILD_DIR)/DEBIAN"
	@install -d "$(STDDEV_BUILD_DIR)/opt/$(STDDEV_PKG)/src"
	@install -d "$(STDDEV_BUILD_DIR)/usr/bin"
	@install -d "$(INSTALL_SRC)"
	@sed 's|__VERSION__|$(VERSION)|g' \
		"$(LINUX_DEPLOY_DIR)/stddev/control.in" \
		> "$(STDDEV_BUILD_DIR)/DEBIAN/control"
	@install -m 755 "$(LINUX_DEPLOY_DIR)/stddev/ivs-stddev" "$(STDDEV_BUILD_DIR)/opt/$(STDDEV_PKG)/ivs-stddev"
	@install -m 755 "$(LINUX_DEPLOY_DIR)/stddev/ivs-stddev" "$(STDDEV_BUILD_DIR)/usr/bin/ivs-stddev"
	@install -m 755 "$(LINUX_DEPLOY_DIR)/stddev/ivs-stddev" "$(STDDEV_BUILD_DIR)/usr/bin/stddev"
	@tar \
		--exclude='html' \
		--exclude='latex' \
		--exclude='.venv' \
		--exclude='.pytest_cache' \
		--exclude='*/.pytest_cache' \
		--exclude='__pycache__' \
		--exclude='*/__pycache__' \
		--exclude='*.pyc' \
		--exclude='*.pyo' \
		-C . -cf - . | tar -C "$(STDDEV_BUILD_DIR)/opt/$(STDDEV_PKG)/src" -xf -
	@find "$(STDDEV_BUILD_DIR)/opt/$(STDDEV_PKG)" -type d -exec chmod 755 {} \;
	@find "$(STDDEV_BUILD_DIR)/opt/$(STDDEV_PKG)" -type f -exec chmod 644 {} \;
	@chmod 755 "$(STDDEV_BUILD_DIR)/opt/$(STDDEV_PKG)/ivs-stddev"
	@chmod 755 "$(STDDEV_BUILD_DIR)/usr/bin/ivs-stddev"
	@chmod 755 "$(STDDEV_BUILD_DIR)/usr/bin/stddev"
	@dpkg-deb --root-owner-group -Zgzip --build "$(STDDEV_BUILD_DIR)" "$(STDDEV_DEB)"

clean-installers:
	@rm -rf "$(DEB_BUILD_DIR)"
	@rm -rf "$(INSTALL_SRC)"

pack: doc installers
	@set -e; \
	rm -f "$(PACK_OUTPUT)"; \
	TMP_DIR="$$(mktemp -d)"; \
	PACK_DIR="$$TMP_DIR/$(TEAM_DIR)"; \
	mkdir -p "$$PACK_DIR/doc" "$$PACK_DIR/install" "$$PACK_DIR/repo"; \
	cp -a "$(DOC_SRC)/." "$$PACK_DIR/doc/"; \
	cp -a "$(INSTALL_SRC)/." "$$PACK_DIR/install/"; \
	cp -a "$(ROOT)/." "$$PACK_DIR/repo/"; \
	rm -f "$$PACK_DIR/repo/$(PACK_NAME)"; \
	rm -rf "$$PACK_DIR/repo/build"; \
	rm -rf "$$PACK_DIR/repo/.idea"; \
	rm -rf "$$PACK_DIR/repo/.vscode"; \
	rm -rf "$$PACK_DIR/repo/src/html" "$$PACK_DIR/repo/src/latex"; \
	find "$$PACK_DIR/repo" -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true; \
	find "$$PACK_DIR/repo" -type f \( -name "*.pyc" -o -name "*.pyo" -o -name ".DS_Store" \) -delete; \
	rm -rf "$$PACK_DIR/repo/src/.pytest_cache" "$$PACK_DIR/repo/src/.venv"; \
	(cd "$$TMP_DIR" && zip -rq "$(PACK_NAME)" "$(TEAM_DIR)"); \
	mv "$$TMP_DIR/$(PACK_NAME)" "$(PACK_OUTPUT)"; \
	rm -rf "$$TMP_DIR"; \
	echo "Created $(PACK_OUTPUT)"

clean:
	find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
	find . -type f \( -name "*.pyc" -o -name "*.pyo" -o -name ".DS_Store" \) -delete
	rm -rf .pytest_cache
	rm -rf "$(VENV_DIR)"
	rm -rf html
	rm -rf latex
	rm -rf $(BUILD_DIR)
	rm -rf ../.idea
	rm -rf ../.vscode

help:
	@echo "Usage:"
	@echo "  make              - prepare the project (default = all)"
	@echo "  make all          - install dependencies and prepare the project"
	@echo "  make deps         - install system packages and Python dependencies into .venv"
	@echo "  make deps-system  - install required Ubuntu packages using apt-get"
	@echo "  make deps-python  - create .venv and install Python dependencies"
	@echo "  make venv-reset   - remove and recreate the Python virtual environment"
	@echo "  make run          - run the application"
	@echo "  make stddev       - run the standard deviation profiling program"
	@echo "  make test         - run math library tests"
	@echo "  make doc          - generate documentation using Doxygen"
	@echo "  make installers   - prepare installer output"
	@echo "  make pack         - generate documentation, prepare installers, and create the submission ZIP archive"
	@echo "  make clean        - remove generated files"
