#!/bin/bash
# enter
#
# Using this tool, we can seek a whole chain if available from an
# IPFS CID or an IPNS link. Default (no arguments) will retrieve
# the local ZCHAIN starting from the IPFS CID stored in the file
# that is tracked by the $ZLATEST environment variable.
#
# enter [-n IPNS_LINK]
# enter [IPFS CID]
# enter
#
# Returns a JSON array representing the chain retrieved and logs
# messages to LOGSFILE

usage(){
	echo "enter - Crawl an arching kaos chain"
	echo "-----------------------------------"
	echo "Usage:"
	echo "	--help, -h				Print this help and exit"
	echo "	--chain <ipns-link>, -n <ipns-link>	Crawl specified chain"
	echo "	--show-zblocks-only, -z			Show only zblocks"
	echo "	--no-verify, -nV			Don't verify signatures"
	echo "	<ipfs-link>				Specify IPFS CID for entrance"
	echo ""
	echo "Note that combined flags don't work for now"
	echo "Running with no flags crawls your chain"
}
# Start of tests
#entrance="QmW5WVXCJfhb4peHG6cbEdamC24vZzMX2Vz386vpENh38U"
#entrance="QmNjQq7GkuXGF8kFT1z2Mv3i4JhY7sBXVUmHDiR1zkQjoE"
#entrance="QmbFMke1KXqnYyBBWxB74N4c5SBnJMVAiMNRcGu6x1AwQH"
# End of tests
verify=1
if [ ! -z "$1" ] && [ "$1" == "-h" ] || [ "$1" == "--help" ]
then
	usage
	exit
elif [ ! -z "$1" ] && [ "$1" == "-nV" ] || [ "$1" == "--no-verify" ]
then
	verify=0
	entrance="$(cat $ZLATEST)"
elif [ ! -z "$1" ] && [ "$1" == "-n" ]
then
	entrance="$(ipns-resolve $2)"
elif [ ! -z "$1" ] && [ "$1" == "--show-zblocks-only" ] || [ "$1" == "-z" ]
then
	# Enter temp folder
	TEMPASSIN="/tmp/aktmp_$(date -u +%s)"
	mkdir $TEMPASSIN
	cd $TEMPASSIN
	ccounter=0
	entrance="$(cat $ZLATEST)"
	seed="$(cat $ZGENESIS)"
	echo '['
	zblock=$entrance
	while true
	do
		if [ "$counter" == 0 ]
		then
			echo "["
		fi
		counter=$(expr $counter + 1)
		if [ ! -v $zblock ]
		then
			if [ "$zblock" != "$seed" ]
		then
			timestamp=''
			echo '{"zblock":"'$zblock'",'
			ipfs cat $zblock | json2bash > $TEMPASSIN/tmp-zblock
			source $TEMPASSIN/tmp-zblock
			ipfs cat $block | json2bash > $TEMPASSIN/tmp-block
			source $TEMPASSIN/tmp-block
			logthis "[INFO]" "BLOCK REFERENCED"
			if [ ! -v $timestamp ]
			then
				echo '"timestamp":"'$timestamp'",'
			fi
			echo '"block_signature":"'$block_signature'",'
			echo '"gpg":"'$gpg'",'

			if [ -v $previous ]
			then
				logthis "[ERROR]" "Block $block has no previous zblock $previous. Appending default genesis to close cleanly."
				echo '"previous":"genesis"},{"genesis":"genesis"}]'
				exit 0
			else
				echo '"previous":"'$previous'"},'
				zblock=$previous
			fi
		elif [ "$zblock" == "$seed" ]
		then
			echo '{"genesis":"genesis"}]'
			logthis "[INFO]" "Counter $counter"
			exit 0
		fi
	else
		echo "Check not passed... No previous IPFS CID"
		exit 1
	fi
done

elif [ ! -z "$1" ]
then
	entrance="$1"
else
	# By default we enter from the latest block
	# We can alter this by changing this value
	entrance="$(cat $ZLATEST)"
fi
# We assign the IPFS CIDv0 of an empty file as this is used
# as our GENESIS block, hence the "seed" that the tree grows
# from.
seed="$(cat $ZGENESIS)"

# We assume that we found the entrance inside a block, hence
# ZBLOCK is labeled as previous
zblock="$entrance"

# Enter temp folder
TEMPASSIN="/tmp/aktmp_$(date -u +%s)"
mkdir $TEMPASSIN
cd $TEMPASSIN
counter=0
# The loop
# We break the loop from inside the loop
while true
do
	if [ $counter == 0 ]
	then
		echo '['
	fi
	counter=$(expr $counter + 1)
	# Check if $zblock exists as variable
	if [ ! -v $zblock ]
	then
		# Check if it is not our seed cause if it is we skip this part
		if [ "$zblock" != "$seed" ]
		then
			# Reset timestamp since it's introduced later
			timestamp=''
			# Announce to stdout which ZBLOCK is being read at the moment
			logthis "[INFO]" "Examining $zblock"
			echo '{"zblock":"'$zblock'",'

			# We create files named after each ZBLOCK IPFS CID for later
			# reference. Files are empty.
			touch $ZBLOCKDIR/$zblock
			logthis "[INFO]" "Created reference"

			# We concatenate the zblock's contents, pipe them through filter
			# json2bash and output them to tmp-file
			ipfs cat $zblock | json2bash > $TEMPASSIN/tmp-zblock
			if [ "$?" == 0 ]
			then
				logthis "[INFO]" "ZBLOCK $zblock READ"
			else
				logthis "[ERROR]" "ZBLOCK $zblock READ failed"
				exit 1
			fi

			# Be sure that there are the expected values
			# We need 'block' and 'block_signature' inside a 'zblock'
			# Exit if any is missing
			grep -e 'block_signature' $TEMPASSIN/tmp-zblock > /dev/null 2>&1
			if [ "$?" == 0 ]
			then
				logthis "[INFO]" "ZBLOCK $zblock has block_signature"
			else
				logthis "[ERROR]" "ZBLOCK $zblock has no block_signature"
				exit 1
			fi
			grep -e 'block=' $TEMPASSIN/tmp-zblock > /dev/null 2>&1
			if [ "$?" == 0 ]
			then
				logthis "[INFO]" "ZBLOCK $zblock has block"
			else
				logthis "[ERROR]" "ZBLOCK $zblock has no block"
				exit 1
			fi

			# Supposingly you are on a safe environment and you only have
			# access to your chain, I would consider mild secure to source
			# the files into your bash.
			# File an issue/pull request if you think it can be done better!!
			source $TEMPASSIN/tmp-zblock
			logthis "[INFO]" "ZBLOCK SOURCED"

			# Same as above applies to BLOCK and DATA subparts of each ZBLOCK
			# BLOCKS
			echo '"block":"'$block'",'
			ipfs cat $block | json2bash > $TEMPASSIN/tmp-block
			if [ "$?" == 0 ]
			then
				logthis "[INFO]" "BLOCK $block READ"
			else
				logthis "[ERROR]" "BLOCK $block READ failed"
				exit 1
			fi

			grep -e 'timestamp' -e 'gpg' -e 'data' -e 'action' -e 'detach' -e 'previous' $TEMPASSIN/tmp-block > /dev/null 2>&1
			if [ "$?" == 0 ]
			then
				logthis "[INFO]" "BLOCK $block is a block"
			else
				logthis "[ERROR]" "BLOCK $block is NOT a valid block"
				exit 1
			fi

			source $TEMPASSIN/tmp-block
			logthis "[INFO]" "BLOCK $block SOURCED"
			touch $BLOCKDIR/$block
			logthis "[INFO]" "BLOCK REFERENCED"
			module="$(echo $action | sed -e 's/\// /g' | awk '{ print $1 }')"
			logthis "[INFO]" "DATA is $module module."
			command="$(echo $action | sed -e 's/\// /g' | awk '{ print $2 }')"
			logthis "[INFO]" "COMMAND is $command"
			if [ ! -v $timestamp ]
			then
				echo '"timestamp":"'$timestamp'",'
			fi
			echo '"block_signature":"'$block_signature'",'
			echo '"detach":"'$detach'",'
			echo '"module":"'$module'",'
			echo '"action":"'$command'",'
			echo '"gpg":"'$gpg'",'
			if [ $verify == 1 ]
			then
				ipfs get $gpg > /dev/null 2>&1
				if [ "$?" == 0 ]
				then
					gpg2 --import $gpg > /dev/null 2>&1
					if [ "$?" == 0 ]
					then
						logthis "[INFO]" "$gpg imported."
					else
						logthis "[ERROR]" "Could not import GPG key: $gpg ."
						exit 1
					fi
				else
					logthis "[ERROR]" "Could not get GPG key: $gpg ."
					exit 1
				fi
				ipfs get $block_signature > /dev/null 2>&1
				if [ "$?" == 0 ]
				then
					mv $block_signature $block.asc
					logthis "[GPG]" "Block signature downloaded"
				else
					logthis "[ERROR]" "Error while getting $block_signature for $block"
					exit 1
				fi
				ipfs get $block > /dev/null 2>&1
				if [ "$?" == 0 ]
				then
					logthis "[INFO]" "Downloaded block $block."
				else
					logthis "[ERROR]" "Could not get $block block"
					exit 1
				fi
				gpg2 --verify $block.asc > /dev/null 2>&1
				if [ "$?" == 0 ]
				then
					logthis "[GPG]" "$gpg signature of $block is verified."
				else
					logthis "[ERROR]" "Could not verify $block with GPG key $gpg."
					exit 1
				fi
			fi
			profile show $data
			# DATA (but we don't source it's stuff)
			# Only print to stdout
			#ipfs cat $data
			touch $DATADIR/$data

			# Now, since we sourced the BLOCK to our terminal, we can search
			# for $previous variable. In case we don't find one, we append one
			# and we exit.
			if [ -v $previous ]
			then
				logthis "[WARNING]" "Block $block has no previous zblock, appending pseudo genesis to exit gracefully."
				echo '"previous":"genesis"},{"genesis":"genesis"}]'
				logthis "[INFO]" "Reached pseudo-genesis, counted $counter zblocks."
				exit 0

			# Otherwise, we inform of the sequence
			else
				#echo "$zblock after $previous"
				logthis "[INFO]" "Found a previous block: $previous"
				echo '"previous":"'$previous'"},'
				zblock=$previous
			fi

		# Now check if it is equal to the seed
		# which apparently means we reached the seed.
		elif [ "$zblock" == "$seed" ]
		then
			#echo "$zblock is GENESIS block"
			#echo '"'$zblock'":{ "GENESIS":"GENESIS"}] '
			echo '{"genesis":"genesis"}]'
			logthis "[INFO]" "Reached $seed, counted $counter zblocks."
			exit 0
		fi
	# And finally, if nothing is there exit with error
	else
		echo "Check not passed... No previous IPFS CID"
		exit 1
	fi
done