# book-window.tcl --
#
#	The spell/prayer book window(s) and related commands.
#

namespace eval NSBookWindow {

# NSBookWindow:: --
#
#	Description.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc NSBookWindow oop {

	global Windows

	InitWindow $oop

	NSWindowManager::RegisterWindow book [Info $oop win] \
		"NSBookWindow::GeometryCmd $oop" "" "NSBookWindow::DisplayCmd $oop"

	#
	# Global list of application windows
	#

	set Windows(book,win) [Info $oop win]
	set Windows(book,class) NSBookWindow
	set Windows(book,oop) $oop
}

# NSBookWindow::Info --
#
#	Query and modify info.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc Info {oop info args} {

	global NSBookWindow

	# Set info
	if {[llength $args]} {
		switch -- $info {
			default {
				set NSBookWindow($oop,$info) [lindex $args 0]
			}
		}

	# Get info
	} else {
		switch -- $info {
			default {
				return $NSBookWindow($oop,$info)
			}
		}
	}
}

# NSBookWindow::InitWindow --
#
#	Create the window associated with this object.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc InitWindow oop {

	global NSBookWindow
	global NSCanvist
	global NSToolbar
	global Windows

	set win .book$oop
	toplevel $win
	wm title $win Book

	wm transient $win $Windows(main,win)

	# Start out withdrawn (hidden)
	wm withdraw $win

	# Do stuff when window closes
	wm protocol $win WM_DELETE_WINDOW "NSBookWindow::Close $oop"

	set NSBookWindow($oop,win) $win

	#
	# Menus
	#

	InitMenus $oop

	#
	# Toolbar
	#

	set toolId [NSObject::New NSToolbar 20 $win]
	NSToolbar::AddTool $toolId Image_ButtonOptions "DoCommandIfAllowed ="
	NSToolbar::AddTool $toolId Image_ButtonHelp "DoCommandIfAllowed ?"

	#
	# Divider
	#

	frame $win.divider2 \
		-borderwidth 1 -height 2 -relief groove

	#
	# List
	#

	frame $win.frame \
		-borderwidth 1 -relief sunken

	set font [Global font,fixed,normal]
	InitHeader $win.frame 2 $font {Name 3 nw Level 40 ne Mana 45 ne \
		Fail 50 ne Comment 51 nw}

	set canvistId [NSObject::New NSCanvist $win.frame 20 400 300 \
		"NSBookWindow::NewItemCmd $oop" "NSBookWindow::HighlightItemCmd $oop"]
	set canvas $NSCanvist($canvistId,canvas)
	ListBackgroundChanged $canvas
	$canvas configure -yscrollcommand "$win.frame.scroll set"
	scrollbar $win.frame.scroll \
		-borderwidth 0 -command "$canvas yview" -orient vert

	# This call updates the list background color whenever the
	# global list background color changes
	set NSBookWindow($oop,clientId) \
		[NSValueManager::AddClient listBG "ListBackgroundChanged $canvas"]

	set NSBookWindow($oop,list) $canvistId

	pack $win.frame.scroll -side right -fill y
	pack $win.frame.header \
		-side top -fill x
	pack $canvas -side left -expand yes -fill both

	#
	# Double-click to select spell
	#

	set NSCanvist($canvistId,invokeCmd) "NSBookWindow::Invoke $oop"

	#
	# Statusbar
	#

	frame $win.statusBar -relief flat -borderwidth 0
	label $win.statusBar.label -anchor w -relief sunken -padx 2
	label $win.statusBar.label2 -anchor w -relief sunken -padx 2 -width 12
	pack $win.statusBar.label -side left -expand yes -fill both
	pack $win.statusBar.label2 -side right -expand no

	#
	# Geometry
	#

	grid rowconfig $win 0 -weight 0 -minsize 0
	grid rowconfig $win 1 -weight 0 -minsize 0
	grid rowconfig $win 2 -weight 1 -minsize 0
	grid rowconfig $win 3 -weight 0 -minsize 0
	grid columnconfig $win 0 -weight 1 -minsize 0
 
	pack forget $NSToolbar($toolId,frame)
	grid $NSToolbar($toolId,frame) -in $win \
		-row 0 -column 0 -rowspan 1 -columnspan 1 -sticky ew
	grid $win.divider2 -in $win \
		-row 1 -column 0 -rowspan 1 -columnspan 1 -sticky ew
	grid $win.frame -in $win \
		-row 2 -column 0 -rowspan 1 -columnspan 1 -sticky news
	grid $win.statusBar -in $win \
		-row 3 -column 0 -rowspan 1 -columnspan 1 -sticky ew

	#
	# Context Menu
	#
	
	set m $win.context
	menu $m -tearoff 0
	bind $canvas <Button-3> "::NSBookWindow::ContextMenu $oop $m %X %Y"

	#
	# Feed Term when keys pressed
	#

	bind $win <KeyPress> {
		angband keypress %A
	}

	#
	# Synch the scrollbars when window is shown.
	#

	bind $win.frame.scroll <Map> "NSBookWindow::SynchScrollBars $oop"

	bind $win <FocusIn> "if !\[string compare %W $win] {focus $canvas}"
}

# NSBookWindow::InitMenus --
#
#	Create the menus associated with the window.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc InitMenus oop {

	global NSBookWindow

	set win $NSBookWindow($oop,win)
}

# NSBookWindow::DisplayCmd --
#
#	Called by NSWindowManager::Display().
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc DisplayCmd {oop message first {bookNum ""}} {

	switch -- $message {
		preDisplay {
			SetList $oop $bookNum
		}
		postDisplay {
		}
	}
}

# NSBookWindow::GeometryCmd --
#
#	Called by NSWindowManager::Setup(). Returns the desired (default)
#	geometry for the window.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc GeometryCmd oop {

	global Windows

	set win [Info $oop win]
	set winMain $Windows(main,win)
	set winMicro $Windows(micromap,win)
	set x [winfo x $winMain]
	set y [winfo y $winMain]
	set width [NSToplevel::ContentWidth $win [expr [NSToplevel::EdgeRight $winMicro] - $x]]
	set height [NSToplevel::ContentHeight $win [expr [NSToplevel::EdgeBottom $winMain] - $y]]
	return ${width}x$height+$x+$y
}

# NSBookWindow::Close --
#
#	Description.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc Close oop {

	angband keypress \033
}

# NSBookWindow::Invoke --
#
#	When a spell is double-clicked, "angband keypress" the
#	char.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc Invoke {oop canvistId x y} {

	global NSCanvist
	global NSBookWindow

	if {[lsearch -exact [angband inkey_flags] INKEY_SPELL] == -1} return

	set row [NSCanvist::PointToRow $canvistId $x $y]
	if {$row == -1} return

	set itemDesc [lindex [angband spell $NSBookWindow($oop,bookNum)] $row]
	angband keypress [lindex $itemDesc 0]
}

# NSBookWindow::ContextMenu --
#
#	When a spell is right-clicked, pop up a context
#	menu of actions.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc ContextMenu {oop menu x y} {

	global NSCanvist
	global NSBookWindow

	set canvistId $NSBookWindow($oop,list)
	set canvas $NSCanvist($canvistId,canvas)

	set x1 [expr $x - [winfo rootx $canvas]]
	set y1 [expr $y - [winfo rooty $canvas]]
	set row [NSCanvist::PointToRow $canvistId $x1 $y1]
	if {$row == -1} return

	set bookNum $NSBookWindow($oop,bookNum)
	set charBook [string index " abcdefghi" $bookNum]

	set spells [angband spell $bookNum]
	set spellDesc [lindex $spells $row]
	set charSpell [lindex $spellDesc 0]

	# Always use "cast" in ZAngband, never "pray"
	set charCmd m

	$menu delete 0 end

	if {[lindex $spellDesc 6]} {
		$menu add command -label Cast/Pray -command "DoUnderlyingCommand $charCmd$charBook$charSpell"
	}
	$menu add command -label Study -command {}

	tk_popup $menu $x $y
}

# NSBookWindow::SetList --
#
#	Fill the list with spells from the given book.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc SetList {oop bookNum} {

	global NSBookWindow
	global NSCanvist

	set win $NSBookWindow($oop,win)
	set canvistId $NSBookWindow($oop,list)
	set canvas $NSCanvist($canvistId,canvas)

	NSCanvist::Delete $canvistId 0 end

	set unknown 0
	set spells [angband spell $bookNum]
	foreach spellDesc $spells {
		eval NSCanvist::Insert $canvistId end $spellDesc

		# Count unknown spells
		if {![lindex $spellDesc 6]} {
			incr unknown
		}
	}

	set type spell

	# This extracts the type of book "Life", "Sorcery", "Chaos" from
	# the tval name "TV_LIFE_BOOK" etc.
	angband k_info info $bookNum attrib
	set bookType [string range $attrib(tval) 3 \
		[expr [string length $attrib(tval)] - 6]]
	set bookType [string index $bookType 0][string tolower [string range $bookType 1 end]]

	# Display number of known/unknown spells
	if $unknown {
		$win.statusBar.label configure -text "$unknown unknown"
	} else {
		$win.statusBar.label configure -text ""
	}
	$win.statusBar.label2 configure -text "[llength $spells] ${type}s"

	# Remember the book being displayed
	set NSBookWindow($oop,bookNum) $bookNum

	# Set window title
	angband k_info info $bookNum attrib
	set name [string trim $attrib(name) \[\]]
	wm title $win "$bookType Book - $name"
}

# NSBookWindow::SynchScrollBars --
#
#	There is a bug (my bug or in Tk?) which prevents the scroll bars
#	from synchronizing when the window is not mapped. So I bind to
#	the <Map> event and synch the scroll bars here.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc SynchScrollBars oop {

	global NSCanvist
	global NSBookWindow

	set win $NSBookWindow($oop,win)
	set canvistId $NSBookWindow($oop,list)
	set canvas $NSCanvist($canvistId,canvas)

	eval $win.frame.scroll set [$canvas yview]
	$canvas yview moveto 0.0
}

# NSBookWindow::NewItemCmd --
#
#	Called by NSCanvist::InsertItem() to create a list row.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc NewItemCmd {oop canvistId y char desc level mana fail info okay} {

	global NSCanvist

	set c [NSCanvist::Info $canvistId canvas]
	set lineHeight [NSCanvist::Info $canvistId rowHgt]
	set font [Global font,fixed,normal]

	set text "$char) $desc"
	set textLeft 5

	set cw [font measure $font "W"]
	set fw [font measure $font $text]
	set fh [font metrics $font -linespace]
	set diff [expr int([expr ($lineHeight - $fh) / 2])]

	# Selection rectangle inside row
	lappend itemIdList [$c create rectangle 2 [expr $y + 2] \
		[expr [winfo width $c] - 3] [expr $y + $lineHeight - 2] \
		-fill "" -outline "" -tags enabled -width 2.0]

	# Text
	lappend itemIdList [$c create text $textLeft [expr $y + $diff] \
		-text $text -anchor nw -font $font -fill White -tags enabled]

	set offset 40

	# Level
	lappend itemIdList [$c create text [expr $textLeft + $cw * [incr offset 0]] \
		[expr $y + $diff] \
		-text $level -anchor ne -justify right -font $font -fill White]

	# Mana
	lappend itemIdList [$c create text [expr $textLeft + $cw * [incr offset 5]] \
		[expr $y + $diff] \
		-text $mana -anchor ne -justify right -font $font -fill White]

	# Fail
	lappend itemIdList [$c create text [expr $textLeft + $cw * [incr offset 5]] \
		[expr $y + $diff] \
		-text $fail% -anchor ne -justify right -font $font -fill White]

	# Comment
	lappend itemIdList [$c create text [expr $textLeft + $cw * [incr offset 1]] \
		[expr $y + $diff] \
		-text $info -anchor nw -justify right -font $font -fill White]

	return $itemIdList
}

# NSBookWindow::HighlightItemCmd --
#
#	Called by NSCanvist::Select() to highlight a row.
#
# Arguments:
#	oop					OOP ID. See above.
#	canvistId					OOP ID of NSCanvist object.
#	state					1 or 0 highlight state.
#	args					List of canvas item ids
#
# Results:
#	What happened.

proc HighlightItemCmd {oop canvistId state args} {

	global NSCanvist

	set canvas [NSCanvist::Info $canvistId canvas]
	set itemIdList $args

	set idRect [lindex $itemIdList 0]

	if {[NSUtils::HasFocus $canvas]} {
		set fill [NSColorPreferences::Get listHilite]
	} else {
		set fill [NSColorPreferences::Get listInactive]
	}

	if $state {
		$canvas itemconfigure $idRect -outline $fill

	} else {
		$canvas itemconfigure $idRect -outline {}
	}
}

# namespace eval NSBookWindow
}
