package tk

import (
	

	
	
)

// ColView is a Widget that arranges several widgets in a column.
type ColView interface {
	Widget
	// MutateState mutates the state.
	MutateState(f func(*ColViewState))
	// CopyState returns a copy of the state.
	CopyState() ColViewState
	// Left triggers the OnLeft callback.
	Left()
	// Right triggers the OnRight callback.
	Right()
}

// ColViewSpec specifies the configuration and initial state for ColView.
type ColViewSpec struct {
	// Key bindings.
	Bindings Bindings
	// A function that takes the number of columns and return weights for the
	// widths of the columns. The returned slice must have a size of n. If this
	// function is nil, all the columns will have the same weight.
	Weights func(n int) []int
	// A function called when the Left method of Widget is called, or when Left
	// is pressed and unhandled.
	OnLeft func(w ColView)
	// A function called when the Right method of Widget is called, or when
	// Right is pressed and unhandled.
	OnRight func(w ColView)

	// State. Specifies the initial state when used in New.
	State ColViewState
}

// ColViewState keeps the mutable state of the ColView widget.
type ColViewState struct {
	Columns     []Widget
	FocusColumn int
}

type colView struct {
	// Mutex for synchronizing access to State.
	StateMutex sync.RWMutex
	ColViewSpec
}

// NewColView creates a new ColView from the given spec.
func ( ColViewSpec) ColView {
	if .Bindings == nil {
		.Bindings = DummyBindings{}
	}
	if .Weights == nil {
		.Weights = equalWeights
	}
	if .OnLeft == nil {
		.OnLeft = func(ColView) {}
	}
	if .OnRight == nil {
		.OnRight = func(ColView) {}
	}
	return &colView{ColViewSpec: }
}

func ( int) []int {
	 := make([]int, )
	for  := 0;  < ; ++ {
		[] = 1
	}
	return 
}

func ( *colView) ( func(*ColViewState)) {
	.StateMutex.Lock()
	defer .StateMutex.Unlock()
	(&.State)
}

func ( *colView) () ColViewState {
	.StateMutex.RLock()
	defer .StateMutex.RUnlock()
	 := .State
	.Columns = append([]Widget(nil), .State.Columns...)
	return 
}

const colViewColGap = 1

// Render renders all the columns side by side, putting the dot in the focused
// column.
func ( *colView) (,  int) *term.Buffer {
	 := .CopyState()
	 := len(.Columns)
	if  == 0 {
		// No column.
		return &term.Buffer{Width: }
	}
	if  <  {
		// To narrow; give up by rendering nothing.
		return &term.Buffer{Width: }
	}
	 := distribute(-(-1)*colViewColGap, .Weights())
	var  term.Buffer
	for ,  := range .Columns {
		if  > 0 {
			.Width += colViewColGap
		}
		 := .Render([], )
		.ExtendRight()
	}
	return &
}

// Handle handles the event first by consulting the overlay handler, and then
// delegating the event to the currently focused column.
func ( *colView) ( term.Event) bool {
	if .Bindings.Handle(, ) {
		return true
	}
	 := .CopyState()
	if 0 <= .FocusColumn && .FocusColumn < len(.Columns) {
		if .Columns[.FocusColumn].Handle() {
			return true
		}
	}

	switch  {
	case term.K(ui.Left):
		.Left()
		return true
	case term.K(ui.Right):
		.Right()
		return true
	default:
		return false
	}
}

func ( *colView) () {
	.OnLeft()
}

func ( *colView) () {
	.OnRight()
}

// Distributes fullWidth according to the weights, rounding to integers.
//
// This works iteratively each step by taking the sum of all remaining weights,
// and using floor(remainedWidth * currentWeight / remainedAllWeights) for the
// current column.
//
// A simpler alternative is to simply use floor(fullWidth * currentWeight /
// allWeights) at each step, and also giving the remainder to the last column.
// However, this means that the last column gets all the rounding errors from
// flooring, which can be big. The more sophisticated algorithm distributes the
// rounding errors among all the remaining elements and can result in a much
// better distribution, and as a special upside, does not need to handle the
// last column as a special case.
//
// As an extreme example, consider the case of fullWidth = 9, weights = {1, 1,
// 1, 1, 1} (five 1's). Using the simplistic algorithm, the widths are {1, 1, 1,
// 1, 5}. Using the more complex algorithm, the widths are {1, 2, 2, 2, 2}.
func ( int,  []int) []int {
	 := 
	 := 0
	for ,  := range  {
		 += 
	}

	 := make([]int, len())
	for ,  := range  {
		[] =  *  / 
		 -= []
		 -= 
	}
	return 
}