# book-menu.tcl --
#
#	Implements the Book Menu. Each item is the name of a spell/prayer
#	book, and each sub-menu lists all the spells in that book.
#

namespace eval NSBookMenu {

# Option: Bypass NSMenu::MenuEnable
variable SetupFaster 1

# NSBookMenu::NSBookMenu --
#
#	Object constructor called by NSObject::New().
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc NSBookMenu {oop mbarId} {

	global NSBookMenu

	set NSBookMenu($oop,mbar) $mbarId

	NSObject::New NSMenu $mbarId "-tearoff 0 -postcommand \"NSBookMenu::SetupMenus $oop\" -identifier MENU_BOOK"
	NSMenu::MenuInsertEntry $mbarId -end MENUBAR {-type cascade -menu MENU_BOOK -label "Book" -underline 0 -identifier M_BOOK}

	foreach spell_book [angband player spell_book] {

		set books [angband k_info find -tval $spell_book]
	
		foreach bookNum $books {
			angband k_info info $bookNum attrib
			set name [string trim $attrib(name) \[\]]
			MakeOneBookMenu $oop $bookNum
			lappend entries "-type cascade -menu MENU_BOOK_$bookNum \
				-label \"$name\" -identifier M_BOOK_$bookNum"
		}
	}

	# Divider line if character has 2 realms
	if {[llength [angband player spell_book]] == 2} {
		set entries [linsert $entries 4 "-type separator"]
	}

	NSMenu::MenuInsertEntries $mbarId -end MENU_BOOK $entries
}

# NSBookMenu::MakeOneBookMenu --
#
#	Get a list of spells from the spell/prayer book given by
#	index and append them to the proper (sub)menu.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc MakeOneBookMenu {oop k_idx} {

	global NSBookMenu

	set mbarId $NSBookMenu($oop,mbar)

	set ident MENU_BOOK_$k_idx
	NSObject::New NSMenu $mbarId "-tearoff 0 -identifier $ident"

	set i 1
	foreach spell [angband spell $k_idx] {
		set charSpell [lindex $spell 0]
		lappend entries "-type command -label \"$charSpell [lindex $spell 1]\" \
			-command \"NSBookMenu::Invoke $oop $k_idx $charSpell\" \
			-underline 0 -identifier \"E_SPELL_${k_idx}_$i\""
		incr i
	}

	NSMenu::MenuInsertEntries $mbarId -end $ident $entries
}

# NSBookMenu::SetupMenus --
#
#	Enable entries representing castable spells.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc SetupMenus oop {

	global NSBookMenu

	set mbarId $NSBookMenu($oop,mbar)

	set flag [lindex [angband inkey_flags] 0]

	# If waiting for a command, enable all the allowable books
	# and spells.
	if {![string compare $flag INKEY_CMD]} {
		set books {}
		foreach spell_book [angband player spell_book] {
			foreach book [angband inventory find -tval $spell_book] {
				angband inventory info $book attrib
				if {[lsearch -exact $books $attrib(k_idx)] == -1} {
					lappend books $attrib(k_idx)
				}
			}
		}

	# If waiting for a spell, enable only the book the spell is in.
	} elseif {![string compare $flag INKEY_SPELL]} {
		set books [angband inkey_other]

	} else {
		return
	}

# Hack -- Bypass NSMenu::MenuEnable
if $NSBookMenu::SetupFaster {

	global NSMenu

	set bookMenuId [lindex [NSMenu::_MenuFindEntry $mbarId MENU_BOOK] 0]

	foreach bookNum $books {
		set i 0
		set okay 0
		set menuId [lindex [NSMenu::_MenuFindEntry $mbarId MENU_BOOK_$bookNum] 0]
		set menu $NSMenu($menuId,menu)
		foreach spell [angband spell $bookNum] {
			if {[lindex $spell 6]} {
				$menu entryconfigure $i -state normal
				set okay 1
			}
			incr i
		}
		if $okay {
			set index [lindex [NSMenu::_MenuFindEntry $mbarId M_BOOK_$bookNum] 1]
			$NSMenu($bookMenuId,menu) entryconfigure $index -state normal
		}
	}

} else {

	set identList {}

	foreach bookNum $books {
		set i 1
		set okay 0
		foreach spell [angband spell $bookNum] {
			if {[lindex $spell 6]} {
				lappend identList E_SPELL_${bookNum}_$i
				set okay 1
			}
			incr i
		}
		if $okay {
			lappend identList M_BOOK_$bookNum
		}
	}

	NSMenu::MenuEnable $mbarId $identList
}
}

# NSBookMenu::Invoke --
#
#	Find the book in inventory and "angband keypress" to cast the spell.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc Invoke {oop bookNum charSpell} {

	global NSBookMenu

	set flag [lindex [angband inkey_flags] 0]

	foreach spell_book [angband player spell_book] {
		foreach book [angband inventory find -tval $spell_book] {
			angband inventory info $book attrib
			if {$attrib(k_idx) == $bookNum} {
				if {![string compare $flag INKEY_CMD]} {
					set charCmd m
					set charBook $attrib(char)
					DoUnderlyingCommand $charCmd$charBook$charSpell
				} else {
					angband keypress $charSpell
				}
				break
			}
		}
	}
}

# NSBookMenu::PopupSelect --
#
#	Show a pop-up menu of spell choices.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc PopupSelect {menu x y} {

	global PopupResult

	set bookNum [angband inkey_other]

	set PopupResult 0

	$menu delete 0 end
	set num 0
	foreach spell [angband spell $bookNum] {

		# Can we cast this spell?
		if {![lindex $spell 6]} continue

		# Get the spell char
		set char [lindex $spell 0]

		# Append menu entry
		$menu add command -label "$char [lindex $spell 1]" \
			-command "angband keypress $char ; set PopupResult 1" -underline 0
		incr num
	}

	if $num {$menu add separator}
	$menu add command -label Cancel

	# Pressing and holding Button-3, poping up, then letting go selects 
	# an item, so wait a bit if it was a quick press-release
	after 100

	tk_popup $menu $x $y [expr $num / 2]

	# If the user unposts the menu without choosing an entry, then
	# I want to feed Escape into the Term. I tried binding to the <Unmap>
	# event but it isn't called on Windows(TM).
	after idle {
		if !$PopupResult {
			angband keypress \033
		}
	}
}

# namespace eval NSBookMenu
}
