THIS_MAKEFILE_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST))

### helper funcs
COLOR_NONE=\033[0m
COLOR_GREEN=\033[1;32m
COLOR_RED=\033[1;31m
COLOR_BLUE=\033[1;34m
COLOR_PINK=\033[1;35m
COLOR_YELLOW=\033[1;33m

TMP_DIR=${THIS_MAKEFILE_DIR}/tmp

TEST_INIT=mkdir -p ${TMP_DIR} && rm -rf ${TMP_DIR}/test* && printf "${COLOR_PINK}test-overwrite-$@: ${COLOR_NONE}\n"
TEST_SKIP=printf "${COLOR_BLUE}$@: ${COLOR_YELLOW}Skipped${COLOR_NONE}\n"
TEST_PASS=printf "${COLOR_BLUE}$@: ${COLOR_GREEN}Passed${COLOR_NONE}\n"
TEST_FAIL=(printf "${COLOR_BLUE}$@: ${COLOR_RED}Failed!${COLOR_NONE}\n" && exit 1)

LEAKS=
ifneq ($(LEAKS),)
  PREFIX=leaks 2>/dev/null --atExit --
  SUFFIX=>${TMP_DIR}/leaks.txt; grep leak ${TMP_DIR}/leaks.txt | grep bytes \# # stop processing at this step
  CHECK=\# # don't run this step
else
  PREFIX=
  SUFFIX=>${TMP_DIR}/$@.out
  CHECK=
endif

CCBN=$(shell basename ${CC})

ifeq ($(CCBN),emcc)
ifeq ($(TESTING),1)
  NODE_EXISTS := $(shell command -v node 2>/dev/null)
  ifeq ($(NODE_EXISTS),)
    $(error "NodeJS not found. Install NodeJS to run wasm tests.")
  endif
  PREFIX="node"
endif
endif

help:
	@echo "# run all tests:"
	@echo "    make test"

ifeq ($(EXE),)
  $(error EXE is not defined)
endif

HEADER=row,column,value,timestamp,author

test: \
	test-1 test-2 test-excel-cells test-add test-remove test-old-value test-force \
	test-bulk-add test-bulk-remove test-echo-overwrite-auto test-timestamp

test-1:
	@${TEST_INIT}
	@${PREFIX} ${EXE} dummy.csv clear
	@(${PREFIX} ${EXE} dummy.csv list > ${TMP_DIR}/$@.out && \
	${CMP} ${TMP_DIR}/$@.out expected/$@.out && ${TEST_PASS} || ${TEST_FAIL})

TIMESTAMP=$(shell date +"%s")

test-2:
	@${TEST_INIT}
	@${PREFIX} ${EXE} dummy.csv clear
	@${PREFIX} ${EXE} dummy.csv add 2-1 ABC --no-timestamp
	@(${PREFIX} ${EXE} dummy.csv list > ${TMP_DIR}/$@.out && \
	${CMP} ${TMP_DIR}/$@.out expected/$@.out && ${TEST_PASS} || ${TEST_FAIL})

test-excel-cells:
	@${TEST_INIT}
	@${PREFIX} ${EXE} dummy.csv clear
	@${PREFIX} ${EXE} dummy.csv add C2 EXCEL --no-timestamp
	@(${PREFIX} ${EXE} dummy.csv list > ${TMP_DIR}/$@.out && \
	${CMP} ${TMP_DIR}/$@.out expected/$@.out && ${TEST_PASS} || ${TEST_FAIL})
	@(${PREFIX} ${EXE} dummy.csv list --A1 > ${TMP_DIR}/$@-a1.out && \
	${CMP} ${TMP_DIR}/$@-a1.out expected/$@-a1.out && ${TEST_PASS} || ${TEST_FAIL})

test-add:
	@${TEST_INIT}
	@${PREFIX} ${EXE} dummy2.csv clear
	@${PREFIX} ${EXE} dummy2.csv add 1-2 VAL1 --no-timestamp
	@${PREFIX} ${EXE} dummy2.csv add 2-2 VAL2 --no-timestamp
	@${PREFIX} ${EXE} dummy2.csv add 2-3 VAL3 --no-timestamp
	@${PREFIX} ${EXE} dummy2.csv add 2-4 VAL4 --no-timestamp
	@(${PREFIX} ${EXE} dummy2.csv list > ${TMP_DIR}/$@-list.out && \
	${CMP} ${TMP_DIR}/$@-list.out expected/$@-list.out && ${TEST_PASS} || ${TEST_FAIL})
	@(${PREFIX} ${ECHO_EXE} --apply-overwrites dummy2.csv > ${TMP_DIR}/$@.out && \
	${CMP} ${TMP_DIR}/$@.out expected/$@.out && ${TEST_PASS} || ${TEST_FAIL})

test-remove:
	@${TEST_INIT}
	@${PREFIX} ${EXE} dummy2.csv clear
	@${PREFIX} ${EXE} dummy2.csv add 1-1 V1 --no-timestamp
	@${PREFIX} ${EXE} dummy2.csv add 2-1 V2 --no-timestamp
	@${PREFIX} ${EXE} dummy2.csv add 3-1 V3 --no-timestamp
	@${PREFIX} ${EXE} dummy2.csv add 4-1 V4 --no-timestamp
	@${PREFIX} ${EXE} dummy2.csv remove 2-1
	@(${PREFIX} ${EXE} dummy2.csv list > ${TMP_DIR}/$@-1.out && \
	${CMP} ${TMP_DIR}/$@-1.out expected/$@-1.out && ${TEST_PASS} || ${TEST_FAIL})
	@${PREFIX} ${EXE} dummy2.csv remove 4-1
	@(${PREFIX} ${EXE} dummy2.csv list > ${TMP_DIR}/$@-2.out && \
	${CMP} ${TMP_DIR}/$@-2.out expected/$@-2.out && ${TEST_PASS} || ${TEST_FAIL})
	@(${PREFIX} ${EXE} dummy2.csv remove --all && \
	[ ! -f ".zsv/overwrite/dummy2.csv/overwrite.sqlite3" ] && ${TEST_PASS} || ${TEST_FAIL})

test-old-value:
	@${TEST_INIT}
	@${PREFIX} ${EXE} dummy2.csv clear
	@${PREFIX} ${EXE} dummy2.csv add 1-1 V1 --no-timestamp
	@${PREFIX} ${EXE} dummy2.csv add 2-1 V2 --no-timestamp
	@${PREFIX} ${EXE} dummy2.csv add 3-1 V3 --no-timestamp
	@${PREFIX} ${EXE} dummy2.csv add 4-1 V4 --no-timestamp
	@(${PREFIX} ${EXE} dummy2.csv add 3-1 NEW_V4 --no-timestamp 2> ${TMP_DIR}/$@-fail.out || \
	${CMP} ${TMP_DIR}/$@-fail.out expected/$@-fail.out && ${TEST_PASS} || ${TEST_FAIL})
	@${PREFIX} ${EXE} dummy2.csv remove 2-1 --old-value V3
	@(${PREFIX} ${EXE} dummy2.csv list > ${TMP_DIR}/$@-1.out && \
	${CMP} ${TMP_DIR}/$@-1.out expected/$@-1.out && ${TEST_PASS} || ${TEST_FAIL})
	@${PREFIX} ${EXE} dummy2.csv add 2-1 NEW_V2 --old-value V2 --no-timestamp
	@(${PREFIX} ${EXE} dummy2.csv list > ${TMP_DIR}/$@-2.out && \
	${CMP} ${TMP_DIR}/$@-2.out expected/$@-2.out && ${TEST_PASS} || ${TEST_FAIL})
	@${PREFIX} ${EXE} dummy2.csv remove 3-1 --old-value V3
	@(${PREFIX} ${EXE} dummy2.csv list > ${TMP_DIR}/$@-3.out && \
	${CMP} ${TMP_DIR}/$@-3.out expected/$@-3.out && ${TEST_PASS} || ${TEST_FAIL})

test-force:
	@${TEST_INIT}
	@${PREFIX} ${EXE} dummy2.csv clear
	@${PREFIX} ${EXE} dummy2.csv add 1-2 VAL1 --no-timestamp
	@${PREFIX} ${EXE} dummy2.csv add 2-2 VAL2 --no-timestamp
	@${PREFIX} ${EXE} dummy2.csv add 2-3 VAL3 --no-timestamp
	@${PREFIX} ${EXE} dummy2.csv add 2-4 VAL4 --no-timestamp
	@(${PREFIX} ${EXE} dummy2.csv add 2-4 NEW_VAL4 --no-timestamp 2> ${TMP_DIR}/$@-fail.out || \
	${CMP} ${TMP_DIR}/$@-fail.out expected/$@-fail.out && ${TEST_PASS} || ${TEST_FAIL})
	@(${PREFIX} ${EXE} dummy2.csv list > ${TMP_DIR}/$@-1.out && \
	${CMP} ${TMP_DIR}/$@-1.out expected/$@-1.out && ${TEST_PASS} || ${TEST_FAIL})
	@(${PREFIX} ${EXE} dummy2.csv add 2-4 NEW_VAL4 --no-timestamp --force && \
	${PREFIX} ${EXE} dummy2.csv list > ${TMP_DIR}/$@-2.out && \
	${CMP} ${TMP_DIR}/$@-2.out expected/$@-2.out && ${TEST_PASS} || ${TEST_FAIL})

test-bulk-add:
	@${TEST_INIT}
	@${PREFIX} ${EXE} dummy2.csv clear
	@${PREFIX} ${EXE} dummy2.csv add 1-1 OLD_V1 --no-timestamp # for old value test
	@${PREFIX} ${EXE} dummy2.csv add 2-1 OLD_VAL2 --no-timestamp
	@${PREFIX} ${EXE} dummy2.csv bulk-add overwrite.csv
	@(${PREFIX} ${EXE} dummy2.csv list > ${TMP_DIR}/$@.out && \
	${CMP} ${TMP_DIR}/$@.out expected/$@.out && ${TEST_PASS} || ${TEST_FAIL})

test-bulk-remove:
	@${TEST_INIT}
	@${PREFIX} ${EXE} dummy2.csv clear
	@${PREFIX} ${EXE} dummy2.csv add 1-1 OLD_V1 --no-timestamp # for old value test
	@${PREFIX} ${EXE} dummy2.csv add 2-1 OLD_VAL2 --no-timestamp
	@${PREFIX} ${EXE} dummy2.csv bulk-add overwrite.csv
	@${PREFIX} ${EXE} dummy2.csv bulk-remove remove.csv
	@(${PREFIX} ${EXE} dummy2.csv list > ${TMP_DIR}/$@.out && \
	${CMP} ${TMP_DIR}/$@.out expected/$@.out && ${TEST_PASS} || ${TEST_FAIL})

STAT_MOD_TS=$(shell if stat -c %Y Makefile >/dev/null 2>/dev/null; then echo 'stat -c %Y' ; else echo 'stat -f %m' ; fi)
# MOD_TS_OFFSET is to prevent false negative test results due to minor time differences due to second boundary updates,
# or modified time being updated slightly later than the actual overwrite operation.
# Adjust this value if you encounter false negatives.
MOD_TS_OFFSET=3 # seconds
test-timestamp:
	@${TEST_INIT}
	@${PREFIX} ${EXE} dummy2.csv clear
	@(${PREFIX} ${EXE} dummy2.csv add 1-2 ABC && ${STAT_MOD_TS} .zsv/data/dummy2.csv/overwrite.sqlite3 > ${TMP_DIR}/timestamp1.txt)
	@(${PREFIX} ${EXE} dummy2.csv add 1-3 ABC && ${STAT_MOD_TS} .zsv/data/dummy2.csv/overwrite.sqlite3 > ${TMP_DIR}/timestamp2.txt)
	@{ \
		MAX_EXPECTED_TS1=`cat ${TMP_DIR}/timestamp1.txt`; \
		MIN_EXPECTED_TS1=`expr $$MAX_EXPECTED_TS1 - ${MOD_TS_OFFSET}`; \
		SQL_QUERY1="SELECT * FROM data WHERE row=1 AND column=2 AND value='ABC' AND timestamp BETWEEN $$MIN_EXPECTED_TS1 AND $$MAX_EXPECTED_TS1;"; \
		SQL_OUTPUT1=`${PREFIX} ${EXE} dummy2.csv list | ${PREFIX} ${SQL_EXE} "$$SQL_QUERY1"`; \
		[ `echo "$$SQL_OUTPUT1" | wc -l` = 2 ] && ${TEST_PASS} || ${TEST_FAIL}; \
	}
	@{ \
		MAX_EXPECTED_TS2=`cat ${TMP_DIR}/timestamp2.txt`; \
		MIN_EXPECTED_TS2=`expr $$MAX_EXPECTED_TS2 - ${MOD_TS_OFFSET}`; \
		SQL_QUERY2="SELECT * FROM data WHERE row=1 AND column=3 AND value='ABC' AND timestamp BETWEEN $$MIN_EXPECTED_TS2 AND $$MAX_EXPECTED_TS2;"; \
		SQL_OUTPUT2=`${PREFIX} ${EXE} dummy2.csv list | ${PREFIX} ${SQL_EXE} "$$SQL_QUERY2"`; \
		[ `echo "$$SQL_OUTPUT2" | wc -l` = 2 ] && ${TEST_PASS} || ${TEST_FAIL}; \
	}

test-echo-overwrite-auto:
	@${TEST_INIT}
	@${PREFIX} ${EXE} dummy.csv clear
	@${PREFIX} ${EXE} dummy.csv add 1-0 ABC
	@${PREFIX} ${EXE} dummy.csv add 2-2 123
	@(${PREFIX} ${ECHO_EXE} --apply-overwrites dummy.csv > ${TMP_DIR}/$@.out && \
	${CMP} ${TMP_DIR}/$@.out expected/$@.out && ${TEST_PASS} || ${TEST_FAIL})

clean:
	rm -rf ${TMP_DIR}

.PHONY: help test% clean
