#!/bin/bash

#===========================================================================
# Copyright ©Oct2012 - Copyright J. S. Gilstrap - johng@mylinuxisp.com
#
# This program 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; version 2 of the License.
#
# This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Any knowledge gained by viewing and/or using this software may NOT be used
# to file for any 'submarine' patents on applicable algorithmns and/or ideas
# or any other method that would undermine the free use and/or distribution
# thereof. By viewing and/or using this software you agree to these terms.
# If you cannot agree to this then do NOT view and/or use this software.
#
# :set syntax=sh


BashVer=`bash --version | grep "^GNU.*bash.*version"` ; BashVer=${BashVer#*version }
# Check bash version.
if [ ${BashVer%%.*} -lt 4 ]
then
	echo "This script requires bash version 4 or greater."
	exit 1
fi

Version=3.4.2
# Check for QR Encode.
if ! which qrencode > /dev/null 2>&1
then
	echo "Can't find 'qrencode' . Quitting."
	exit 1
else
	QRver=`qrencode -V 2>&1 | grep 'qrencode version'`
	if [ "${QRver#*version }" != $Version ]
	then
		echo "'mkqr' is written for version $Version of qrencode. Quitting."
		exit 1
	fi
fi

# Check for get_string function.
if which get_string > /dev/null 2>&1
then
	. get_string
	MAXLNTH=32
else
	echo "Can't find 'get_string' function. Quitting."
	exit 1
fi

# Check for zenity (version)
if ! which zenity > /dev/null 2>&1
then
	echo "Can't find 'zenity'"
	echo "You will not be able to use visual color selection, file open dialog and text-info."
	zver=0
	sleep 1.5

else
	zVer=$(zenity --version) ; zver=${zVer%.*} ; M=${zver%.*} ; m=${zver#*.}
	if [ "$M" -eq 2 -a "$m" -lt 32 ]
	then
		echo "Visual color selection using zenity $zVer will not be available."
		zver=1
		sleep 1.5
	else
		zver=2
	fi
fi

# Clear and set variables.
unset InPutFile OutPutFile ModSize ErrCor SymVer Margin DPI Type Struct Kangi Lwr8Bit Ignore Eight Micro
FGcolor=#000000 ; BGcolor=#FFFFFF
[ -n "$1" ] && { inFile="$1" ; OutPutFile=${1%.*} ; }

### Define functions.
# PreRUles
pRule()
	{
	[ -z "$GTlnth" ] && GTlnth=1

	if [ $LENGTH -gt $GTlnth ]
	then
		printf "[1mString longer than $GTlnth character(s). Trimming to length.\n[0m"
		STRING=${STRING:0:${GTlnth}}
		LENGTH=$GTlnth
	fi
	}

# Ask If OK.
isOK()
	{
	[ -z "$YN" ] && YN=y
	printf "\nIs this OK? [y|Y|n|N] <${YN}> : "
	read yn ; yn=${yn,,} ; yn=${yn:0:1}

	if [ -n "$yn" ]
	then
		if [ $yn = y ]
		then
			break 1
		else
			YN=$yn
		fi
	else
		[ $YN = y ] && break 1
	fi
	}

# Select Output Type.
outputType()
	{
	printf "\n\tSelect output type\n\n"

	select T in PNG EPS SVG ANSI ANSI256 ASCII ASCIIi UTF8 ANSIUTF8
	do
		Type=$T
		Ext=${T,,}
		break 1
	done
	}

# Change Color.
chColor()
	{ 
	local clr color
	eval color=\$$1
	clr=`zenity --title="$2" --color-selection --show-palette --color="$color"`
	clr=${clr^^} ; clr=${clr:0:3}${clr:5:2}${clr:9:2}
	eval $1=$clr
	}

# Gather input.
while :
do
	printf "\n\t\t[1mQR Encode UI Wrapper[0m\n\n"
	preRules=pRule

	# Numbered input.
	MATCH="[0-9]" ; ERR_MSG="Use Numbers Only."
	REQUIRED=N ; VALIDATE=Y


	PROMPT="Module size" ; GTlnth=2
	[ -z "$ModSize" ] && ModSize=3
	getString ModSize

	PROMPT="Set margin width" ; GTlnth=1
	[ -z "$Margin" ] && Margin=4 
	getString Margin

	PROMPT="Error corection [l|m|q|h]"
	ERR_MSG="Use l, L, m, M, q, Q, h, or H Only."
	[ -z "$ErrCor" ] && ErrCor=L ; MATCH="[lLmMqQhH]"
	getString ErrCor ; ErrCor=${ErrCor^^}


	# Yes/No Input.
	printf "\n\tYes/No input [y|n]\n\n"
	MATCH="[YyNn]" ; ERR_MSG="Use y, Y, n, or N Only."

	PROMPT="Make structured symbols"
	[ -z "$Struct" ] && Struct=n
	getString Struct ; Struct=${Struct,,}

	PROMPT="Full 8 bit mode"
	[ -z "$Eight" ] && Eight=n
	getString Eight ; Eight=${Eight,,}

	# Options not used in full 8 bit mode.
	case $Eight in
		n)
			PROMPT="Assume kangi input (shift-jis)"
			[ -z "$Kangi" ] && Kangi=n
			getString Kangi ; Kangi="${Kangi,,}" 

			PROMPT="Encode 8-bit lower-case alpha"
			[ -z "$Lwr8Bit" ] && Lwr8Bit=n 
			getString Lwr8Bit ; Lwr8Bit="${Lwr8Bit,,}"

			PROMPT="Convert all alpha to upper-case"
			[ -z "$Ignore" ] && Ignore=n
			getString Ignore ; Ignore="${Ignore,,}"
		;;
		*) unset Kangi Lwr8Bit Ignore
	esac

	PROMPT="Encode in a Micro QR code"
	VALIDATE=Y ; [ -z "$Micro" ] && Micro=n
	getString Micro ; Micro="${Micro,,}" 

	unset preRules

	echo
	PROMPT="Symbol version number (1 to 40)"
	MATCH="[0-9A]" ; ERR_MSG="Use Numbers Only."
	[ -z "$SymVer" ] && SymVer=A

	[ $Struct = y -o $Micro  = y ] && REQUIRED=Y
	[ $Struct = y -a $SymVer = A ] && unset SymVer
	getString SymVer

	if [ "$SymVer" != A ]
	then
		if [ $Micro = y ]
		then
			[ $SymVer -gt 4  ] && SymVer=4
		else
			[ $SymVer -gt 40 ] && SymVer=40
		fi
	fi

	PROMPT="Set DPI of generated image"
	MATCH="[0-9]" ; REQUIRED=N ; [ -z "$DPI" ] && DPI=72
	getString DPI

	unset MATCH ERR_MSG
	PROMPT="Output File"
	REQUIRED=Y ; VALIDATE=N
	getString OutPutFile

	# Set output type
	if [ -z "$Type" ]
	then
		outputType
	else
		[ -z "$chTyp" ] && chTyp=n
		printf "\nChange output type? [Y|y|N|n] <${chTyp}> : "
		read chtyp

		if [ -n "$chtyp" ]
		then
			chtyp=${chtyp,,} ; chTyp=${chtyp:0:1}
		fi

		[ "$chTyp" = y ] && outputType
	fi

	# Set Colors.
	if [ "$zver" -eq 2 ] && [ "$Type" = PNG -o "$Type" = SVG ]
	then
		printf "\nForeground Color : $FGcolor   Background Color : $BGcolor\n"
		[ -z "$chClr" ] && chClr=n
		printf "Change colors? [Y|y|N|n] <${chClr}> : "
		read chclr

		if [ -n "$chclr" ]
		then
			chclr=${chclr,,} ; chClr=${chclr:0:1}
		fi

		if [ "$chClr" = y ]
		then
			chColor FGcolor 'Foreground Color'
			chColor BGcolor 'Background Color'
		fi
	fi

	clear

	cat<<TheEnd

	           Module Size : $ModSize
	          Margin Width : $Margin
	        Symbol Version : $SymVer
	      Error Correction : $ErrCor
	    Structured Symbols : $Struct
	            Full 8 Bit : $Eight
	           Kangi Input : $Kangi
	8 Bit Lower Case Alpha : $Lwr8Bit
	         Micro QR Code : $Micro
	             Image DPI : $DPI
	           Output File : ${OutPutFile}.${Ext}
	           Output Type : $Type
	      Foreground Color : $FGcolor
	      Background Color : $BGcolor
 
TheEnd
	isOK
done
[ "$SymVer" = A ] && unset SymVer

# Get QR content.
YN=y ; printf "Specify an input file? [y|Y|n|N] <${YN}> : "
read yn ; yn=${yn,,} ; yn=${yn:0:1} ; [ -n "$yn" ] && YN=$yn

if [ $YN = y ]
then
	while :
	do
		while [ -z "$InPutFile" ]
		do
			if [ "$zver" -ge 1 ]
			then
				InPutFile=`zenity --file-selection --title='QR Content Input File' --filename=${PWD}/${inFile}`
			else
				printf "Enter path to text input file : "
				read InPutFile
			fi
		done

		if [ -r "$InPutFile" -a -s "$InPutFile" ]
		then
			Content=`cat "$InPutFile"`
			clear ; printf "\n${Content//%/%%}\n\n"
			isOK
			unset InPutFile
		else
			printf "File is not readable by user or is empty. Quit? [q] : "
			read Q ; [ "$Q" = q ] && exit 1
			unset InPutFile
		fi
	done
else
	while :
	do
		printf "Enter QR content. End with Ctrl-D\n\n"
		Content=`cat`
		clear ; printf "\n${Content//%/%%}\n\n"
		isOK
	done
fi

# Prepend the proper switches.
for VAR in OutPutFile ModSize ErrCor SymVer Margin DPI Type Struct Kangi Lwr8Bit Ignore Eight Micro FGcolor BGcolor
do
	unset sw
	eval var=\$$VAR
	case $var in n) unset var ;; esac

	if [ -n "$var" ]
	then
		case $VAR in
			OutPutFile) sw='-o ' ;;
			   ModSize) sw='-s ' ;;
			    ErrCor) sw='-l ' ;;
			    SymVer) sw='-v ' ;;
			    Margin) sw='-m ' ;;
			       DPI) sw='-d ' ;;
			      Type) sw='-t ' ;;
			    Struct) sw='-S ' ;;
			     Kangi) sw='-k ' ;;
			   Lwr8Bit) sw='-c ' ;;
			    Ignore) sw='-i ' ;;
			     Eight) sw='-8 ' ;;
			     Micro) sw='-M ' ;;
			   FGcolor) sw='--foreground=' ; var=${var:1:6} ;;
			   BGcolor) sw='--background=' ; var=${var:1:6} ;;
		esac

		case $VAR in Struct|Kangi|Lwr8Bit|Ignore|Eight|Micro) unset var ;; esac
		eval $VAR=\"$sw$var\"
	else
		unset $VAR
	fi
done

# Run qrencode.
OutPutFile="${OutPutFile}.${Ext}"
qrencode $OutPutFile $ModSize $ErrCor $SymVer \
$Margin $DPI $Type $Struct $Kangi $Lwr8Bit \
$Ignore $Eight $Micro $FGcolor $BGcolor "${Content}"
if [ $? -eq 0 ]
then
	echo "Output File : ${OutPutFile#-o }"
else
	printf "[1m E R R O R ! [0m\n"
fi

# Display QR Code.
if which display > /dev/null 2>&1
then
	printf "Display QR Code ? [y|Y] : "
	read disp
	case $disp in y|Y) display ${OutPutFile/-o } ;; esac
fi

