#!/usr/bin/wish
set installdir /usr/local/tkbible

set version "0.03"
wm title . "tkBible $version"
wm minsize . 600 400
wm protocol . WM_DELETE_WINDOW {tkbible_close}
global current_book

set home $env(HOME)

#
#----------- configuration -------------#
#
### set defaults ###
set options(list) {textwidth textheight listfontfam listfontsize listfontwght listfontslnt textfontfam textfontsize textfontwght textfontslnt}
set options(textwidth) 60
set options(textheight) 20
set options(listfontfam) ""
set options(listfontsize) 10
font create listfont -size 10
set options(textfontfam) ""
set options(textfontsize) 10
font create textfont -size 10

if {[file exists $home/.tkbible.conf] == 1} {
	set fid [open $home/.tkbible.conf]
	while {[eof $fid] != 1} {
		set line [gets $fid]
		set cut [string first ":" $line]
		incr cut -1
		set name [string range $line 0 $cut]
		incr cut 2
		set value [string range $line $cut end]
		set options($name) $value
	}
	close $fid
	font configure listfont -family $options(listfontfam) -size $options(listfontsize)\
		-weight $options(listfontwght) -slant $options(listfontslnt)
	font configure textfont -family $options(textfontfam) -size $options(textfontsize)\
		-weight $options(textfontwght) -slant $options(textfontslnt)
}

#
#---------------main menubar-----------------#
#
frame .mbar -borderwidth 1 -relief raised
pack .mbar -fill x
menubutton .mbar.file -text "File" -menu .mbar.file.m
pack .mbar.file -side left
menu .mbar.file.m -tearoff no
.mbar.file.m add command -label "Search" -command edit_search
.mbar.file.m add separator
.mbar.file.m add command -label "Exit" -command tkbible_close

menubutton .mbar.edit -text "Edit" -menu .mbar.edit.m
pack .mbar.edit -side left
menu .mbar.edit.m -tearoff no
.mbar.edit.m add command -label "Copy" -command {tk_textCopy .main.box}
.mbar.edit.m add separator
.mbar.edit.m add command -label "Preferences" -command pref_dialog

#
#---------------main display-------------#
#
frame .main 
pack .main -expand yes -fill both -padx 5 -pady 5

scrollbar .main.bookbar -command {.main.books yview}
listbox .main.books -width 12 -height $options(textheight) -background lightblue\
	-foreground black -yscrollcommand {.main.bookbar set} -font listfont\
	-exportselection false
pack .main.books -side left -fill y
pack .main.bookbar -side left -fill y

listbox .main.chap -width 4 -height $options(textheight) -background lightyellow\
	-foreground black -yscrollcommand {.main.chapbar set} -font listfont\
	-exportselection false
scrollbar .main.chapbar -command {.main.chap yview}
pack .main.chap -side left -fill y
pack .main.chapbar -side left -fill y

scrollbar .main.bar -command {.main.box yview}
text .main.box -background white -foreground black -height $options(textheight)\
	-width $options(textwidth) -wrap word \
	-yscrollcommand {.main.bar set} \
	-font textfont -state disabled

button .main.prev -text "Previous Chapter" -command prev_chapter
button .main.next -text "Next Chapter" -command next_chapter

pack .main.prev -side top -fill x
pack .main.next -side bottom -fill x
pack .main.bar -side right -fill y
pack .main.box -side right -expand yes -fill both -padx 10 -pady 10


bind .main.books <ButtonRelease-1> {go_book}
bind .main.chap <ButtonRelease-1> {load_chapter}

set file [open $installdir/books]
set book "none"
while {$book != "Revelation"} {
	set line [gets $file]
	set cut [string first "/" $line]
	incr cut -1
	set book [string range $line 0 $cut]
	incr cut 2
	global chapters
	set chapters($book) [string range $line $cut end]
	.main.books insert end $book
}
close $file

#
#------------------processes------------#
#

proc go_book {} {
	global current_book
	.main.books activate [concat [.main.books curselection]]
	set current_book [.main.books get active]
	list_chapters
	.main.chap activate 0
	load_chapter
}

proc list_chapters {} {
	global chapters
	global current_book
	.main.chap delete 0 end
	set temp 0
	while {$temp != $chapters($current_book)} {
		incr temp
		.main.chap insert end $temp
	}
	.main.chap selection set 0
}

proc load_chapter {} {
	global version
	global current_book
	set current_chapter [concat [.main.chap curselection]]
	incr current_chapter
	set target_range "$current_chapter:1-$current_chapter:200"
	.main.box configure -state normal
	.main.box delete 1.0 end
	.main.box insert end [exec bible -l 500 $current_book$target_range]
	.main.box configure -state disabled
	wm title . "tkBible $version- $current_book $current_chapter"

}

proc prev_chapter {} {
	set listpos [.main.chap index active]
	if {$listpos != 0} {
		.main.chap selection clear $listpos
		incr listpos -1
		.main.chap selection set $listpos
		.main.chap activate $listpos
		.main.chap see $listpos
		load_chapter
	}
}

proc next_chapter {} {
	set listpos [.main.chap index active]
	set lastpos [.main.chap index end]
	incr lastpos -1
	if {$listpos != $lastpos} {
		.main.chap selection clear $listpos
		incr listpos
		.main.chap selection set $listpos
		.main.chap activate $listpos
		.main.chap see $listpos
		load_chapter
	}
}

.main.books selection set 0
go_book

#
#---------------Search Interface-----------------#
#

proc edit_search {} {
	toplevel .search
	wm title .search "tkBible Search"
	wm resizable .search 0 0

	frame .search.mbar
	pack .search.mbar -expand yes -fill x
	menubutton .search.mbar.edit -text "Edit" -menu .search.mbar.edit.m
	pack .search.mbar.edit -side left
	menu .search.mbar.edit.m -tearoff no
	.search.mbar.edit.m add command -label "Copy Verse" -command {tk_textCopy .search.show}
	.search.mbar.edit.m add command -label "Copy List" -state disabled

	frame .search.statusbar -relief sunken -borderwidth 2
	pack .search.statusbar -side top -expand yes -fill x
	label .search.statusbar.refs -text "References"
	pack .search.statusbar.refs -side left


	frame .search.list
	pack .search.list -side left -expand yes -fill y

	scrollbar .search.list.bar -command {.search.list.box yview}
	listbox .search.list.box -background lightyellow -foreground black -height 20 -width 12 \
		-yscrollcommand {.search.list.bar set} -font listfont
	pack .search.list.box -side left -expand yes -fill y
	pack .search.list.bar -side left -fill y

	bind .search.list.box <ButtonRelease-1> {show_verse}
	
	text .search.show -width 40 -height 10 -background white -foreground black -wrap word \
		-font textfont -state disabled
	pack .search.show -side top

	frame .search.nav
	pack .search.nav -fill x
	button .search.nav.prev -text "< Previous" -width 20 -command prev_verse
	pack .search.nav.prev -side left
	button .search.nav.next -text "Next >" -width 20 -command next_verse
	pack .search.nav.next -side left


	entry .search.entry -background white -foreground black
	pack .search.entry -pady 30
	bind .search.entry <KeyPress-Return> {search_execute}

	label .search.note -text "Use boolean search strings like \"faith and love\""
	pack .search.note 

	frame .search.buttons
	button .search.buttons.search -text "Search" -width 10 -command search_execute
	button .search.buttons.cancel -text "Cancel" -width 10 -command {destroy .search}
	pack .search.buttons.search -side left -padx 15 -pady 5
	pack .search.buttons.cancel -side left -padx 15 -pady 5
	pack .search.buttons 
}

proc search_execute {} {
	global keystring
	set keystring [.search.entry get]
	wm title .search "tkBible Search - $keystring"
	set n 1
	set done "no"
	if {$keystring != ""} {
		set sphrase "??[word_parse]"
		incr n
	} else {
		set done "yes"
	}
	if {$keystring == ""} {
		set done yes
	}
	while {$done != "yes"} {
		set logicflag [word_parse]
		if {$logicflag == "and"} {
			append sphrase " ?\"and [word_parse]\""
			incr n
		} elseif {$logicflag == "or"} {
			append sphrase " ?\"or [word_parse]\""
			incr n
		} else {
			set done "yes"
		}
		if {$keystring == ""} {
			set done "yes"
		}
	}
	.search.list.box delete 0 end
	show_clear
	.search.statusbar.refs configure -text "References"
	set cmd "bible $sphrase"
	foreach i [exec /bin/sh -c $cmd] {
		if {$n > 1} {
			if {$i == "References"} {
				incr n -1
			}
		} elseif {$n == 1} {
			.search.statusbar.refs configure -text "References $i"
			set n 0
		} else {
			.search.list.box insert end $i
		}
	}
	.search.list.box selection set 0
	show_verse
}

proc show_verse {} {
	.search.show configure -state normal
	.search.list.box activate [concat [.search.list.box curselection]]
	set verse [.search.list.box get active]
	if {$verse != ""} {
		.search.show delete 1.0 end
		.search.show insert end [exec bible -f -l 500 $verse]
		.search.show configure -state disabled
	}
}

proc show_clear {} {
	.search.show configure -state normal
	.search.show delete 1.0 end
	.search.show configure -state disabled
}

proc prev_verse {} {
	set pos [.search.list.box index active]
	if {$pos != 0} {
		.search.list.box selection clear $pos
		incr pos -1
		.search.list.box selection set $pos
		.search.list.box activate $pos
		.search.list.box see $pos
		show_verse
	}
}

proc next_verse {} {
	set pos [.search.list.box index active]
	set end [.search.list.box index end]
	incr end -1
	if {$pos < $end} {
		.search.list.box selection clear $pos
		incr pos
		.search.list.box selection set $pos
		.search.list.box activate $pos
		.search.list.box see $pos
		show_verse
	}
}

proc word_parse {} {
	global keystring
	if {[string match "*\ *" $keystring] ==1} {
		set cut [string first " " $keystring]
		incr cut -1
		set word [string range $keystring 0 $cut]
		incr cut 2
		set keystring [string range $keystring $cut end]
	} else {
		set word $keystring
	}
	return $word
}

proc pref_dialog {} {
	global options
	set options(listfontfam) [font configure listfont -family]
	set options(listfontwght) [font configure listfont -weight]
	set options(listfontslnt) [font configure listfont -slant]
	set options(textfontfam) [font configure textfont -family]
	set options(textfontwght) [font configure textfont -weight]
	set options(textfontslnt) [font configure textfont -slant]

	toplevel .pref
	wm title .pref "Preferences"

	label .pref.lfslbl -text "List Font:"
	grid .pref.lfslbl -columnspan 2
	menubutton .pref.lff -menu .pref.lff.m -width 20\
		-relief raised -indicatoron 1\
		-textvariable options(listfontfam)\
		-text $options(listfontfam)
	#pack .pref.lff -padx 5 -pady 5
	menu .pref.lff.m -tearoff no

	menubutton .pref.lfs -menu .pref.lfs.m -width 10\
		-relief raised -indicatoron 1\
		-textvariable options(listfontsize)\
		-text $options(listfontsize)
	#pack .pref.lfs -padx 5 -pady 5
	grid .pref.lff .pref.lfs -padx 5 -pady 5

	menu .pref.lfs.m -tearoff no
	.pref.lfs.m add radiobutton -label "10" -variable options(listfontsize) -value 10
	.pref.lfs.m add radiobutton -label "12" -variable options(listfontsize) -value 12
	.pref.lfs.m add radiobutton -label "14" -variable options(listfontsize) -value 14

	menubutton .pref.lfw -menu .pref.lfw.m -width 20\
		-relief raised -indicatoron 1\
		-textvariable options(listfontwght)\
		-text $options(listfontwght)
	menu .pref.lfw.m -tearoff no
	.pref.lfw.m add radiobutton -label "normal" -variable options(listfontwght) -value "normal"
	.pref.lfw.m add radiobutton -label "bold" -variable options(listfontwght) -value "bold"

	menubutton .pref.lfsl -menu .pref.lfsl.m -width 10\
		-relief raised -indicatoron 1\
		-textvariable options(listfontslnt)\
		-text $options(listfontslnt)
	menu .pref.lfsl.m -tearoff no
	.pref.lfsl.m add radiobutton -label "roman" -variable options(listfontslnt) -value "roman"
	.pref.lfsl.m add radiobutton -label "italic" -variable options(listfontslnt) -value "italic"
	grid .pref.lfw .pref.lfsl -padx 5 -pady 5

	label .pref.df -text "Text Font:"
	grid .pref.df -columnspan 2
	menubutton .pref.dff -menu .pref.dff.m -width 20\
		-relief raised -indicatoron 1\
		-textvariable options(textfontfam)\
		-text $options(textfontfam)
	#pack .pref.dff -padx 5 -pady 5
	menu .pref.dff.m -tearoff no

	menubutton .pref.dfs -menu .pref.dfs.m -width 10\
		-relief raised -indicatoron 1\
		-textvariable options(textfontsize)\
		-text $options(textfontsize)
	#pack .pref.dfs -padx 5 -pady 5
	grid .pref.dff .pref.dfs -padx 5 -pady 5

	menu .pref.dfs.m -tearoff no
	.pref.dfs.m add radiobutton -label "10" -variable options(textfontsize) -value 10
	.pref.dfs.m add radiobutton -label "12" -variable options(textfontsize) -value 12
	.pref.dfs.m add radiobutton -label "14" -variable options(textfontsize) -value 14

	menubutton .pref.dfw -menu .pref.dfw.m -width 20\
		-relief raised -indicatoron 1\
		-textvariable options(textfontwght)\
		-text $options(textfontwght)
	menu .pref.dfw.m -tearoff no
	.pref.dfw.m add radiobutton -label "normal" -variable options(textfontwght) -value "normal"
	.pref.dfw.m add radiobutton -label "bold" -variable options(textfontwght) -value "bold"

	menubutton .pref.dfsl -menu .pref.dfsl.m -width 10\
		-relief raised -indicatoron 1\
		-textvariable options(textfontslnt)\
		-text $options(textfontslnt)
	menu .pref.dfsl.m -tearoff no
	.pref.dfsl.m add radiobutton -label "roman" -variable options(textfontslnt) -value "roman"
	.pref.dfsl.m add radiobutton -label "italic" -variable options(textfontslnt) -value "italic"
	grid .pref.dfw .pref.dfsl -padx 5 -pady 5

	label .pref.geolbl -text "Custom Geometry"
	grid .pref.geolbl -columnspan 2 -padx 5 -pady 5

	scale .pref.geoth -length 200 -variable options(textheight) -from 1 -to 60\
	-orient horizontal -command geometry_apply -label "Display Height"
	grid .pref.geoth -padx 5 -pady 5 -columnspan 2

	scale .pref.geotw -length 200 -variable options(textwidth) -from 20 -to 120\
	-orient horizontal -command geometry_apply -label "Display Width"
	grid .pref.geotw -padx 5 -pady 5 -columnspan 2

	button .pref.apply -text "Apply" -width 10 -command pref_apply
	button .pref.ok -text "OK" -width 10 -command {pref_apply; destroy .pref}
	grid .pref.apply .pref.ok -padx 5 -pady 5

	set famlist [font families]
	foreach family $famlist {
		.pref.lff.m add radiobutton -label $family -variable options(listfontfam) -value $family
		.pref.dff.m add radiobutton -label $family -variable options(textfontfam) -value $family
	}
}

proc pref_apply {} {
	global options
	font configure listfont -family $options(listfontfam) -size $options(listfontsize)\
		-weight $options(listfontwght) -slant $options(listfontslnt)
	font configure textfont -family $options(textfontfam) -size $options(textfontsize)\
		-weight $options(textfontwght) -slant $options(textfontslnt)
}

proc geometry_apply {null} {
	global options
	.main.books configure -height $options(textheight)
	.main.chap configure -height $options(textheight)
	.main.box configure -height $options(textheight) -width $options(textwidth)
}

proc tkbible_close {} {
	global options
	global home
	set fid [open $home/.tkbible.conf w]
	foreach name $options(list) {
		puts $fid "$name\:$options($name)"
	}
	close $fid
	exit
}


