package cview

import 

// ContextMenu is a menu that appears upon user interaction, such as right
// clicking or pressing Alt+Enter.
type ContextMenu struct {
	parent   Primitive
	item     int
	open     bool
	drag     bool
	list     *List
	x, y     int
	selected func(int, string, rune)

	l sync.RWMutex
}

// NewContextMenu returns a new context menu.
func ( Primitive) *ContextMenu {
	return &ContextMenu{
		parent: ,
	}
}

func ( *ContextMenu) () {
	if .list != nil {
		return
	}

	.list = NewList()
	.list.ShowSecondaryText(false)
	.list.SetHover(true)
	.list.SetWrapAround(true)
	.list.ShowFocus(false)
	.list.SetBorder(true)
	.list.SetPadding(
		Styles.ContextMenuPaddingTop,
		Styles.ContextMenuPaddingBottom,
		Styles.ContextMenuPaddingLeft,
		Styles.ContextMenuPaddingRight)
}

// ContextMenuList returns the underlying List of the context menu.
func ( *ContextMenu) () *List {
	.l.Lock()
	defer .l.Unlock()

	.initializeList()

	return .list
}

// AddContextItem adds an item to the context menu. Adding an item with no text
// or shortcut will add a divider.
func ( *ContextMenu) ( string,  rune,  func( int)) {
	.l.Lock()
	defer .l.Unlock()

	.initializeList()

	 := NewListItem()
	.SetShortcut()
	.SetSelectedFunc(.wrap())

	.list.AddItem()
	if  == "" &&  == 0 {
		.list.Lock()
		 := len(.list.items) - 1
		.list.items[].disabled = true
		.list.Unlock()
	}
}

func ( *ContextMenu) ( func( int)) func() {
	return func() {
		(.item)
	}
}

// ClearContextMenu removes all items from the context menu.
func ( *ContextMenu) () {
	.l.Lock()
	defer .l.Unlock()

	.initializeList()

	.list.Clear()
}

// SetContextSelectedFunc sets the function which is called when the user
// selects a context menu item. The function receives the item's index in the
// menu (starting with 0), its text and its shortcut rune. SetSelectedFunc must
// be called before the context menu is shown.
func ( *ContextMenu) ( func( int,  string,  rune)) {
	.l.Lock()
	defer .l.Unlock()

	.selected = 
}

// ShowContextMenu shows the context menu. Provide -1 for both to position on
// the selected item, or specify a 	position.
func ( *ContextMenu) ( int,  int,  int,  func(Primitive)) {
	.l.Lock()
	defer .l.Unlock()

	.show(, , , )
}

// HideContextMenu hides the context menu.
func ( *ContextMenu) ( func(Primitive)) {
	.l.Lock()
	defer .l.Unlock()

	.hide()
}

// ContextMenuVisible returns whether or not the context menu is visible.
func ( *ContextMenu) () bool {
	.l.Lock()
	defer .l.Unlock()

	return .open
}

func ( *ContextMenu) ( int,  int,  int,  func(Primitive)) {
	.initializeList()

	if len(.list.items) == 0 {
		return
	}

	.open = true
	.item = 
	.x, .y = , 

	.list.Lock()
	for ,  := range .list.items {
		if !.disabled {
			.list.currentItem = 
			break
		}
	}
	.list.Unlock()

	.list.SetSelectedFunc(func( int,  *ListItem) {
		.l.Lock()

		// A context item was selected. Close the menu.
		.hide()

		if .selected != nil {
			.l.Unlock()
			.selected(, string(.mainText), .shortcut)
		} else {
			.l.Unlock()
		}
	})
	.list.SetDoneFunc(func() {
		.l.Lock()
		defer .l.Unlock()

		.hide()
	})

	(.list)
}

func ( *ContextMenu) ( func(Primitive)) {
	.initializeList()

	.open = false

	if .list.HasFocus() {
		(.parent)
	}
}