package cview

import (
	

	
)

// frameText holds information about a line of text shown in the frame.
type frameText struct {
	Text   string      // The text to be displayed.
	Header bool        // true = place in header, false = place in footer.
	Align  int         // One of the Align constants.
	Color  tcell.Color // The text color.
}

// Frame is a wrapper which adds space around another primitive. In addition,
// the top area (header) and the bottom area (footer) may also contain text.
type Frame struct {
	*Box

	// The contained primitive.
	primitive Primitive

	// The lines of text to be displayed.
	text []*frameText

	// Border spacing.
	top, bottom, header, footer, left, right int

	sync.RWMutex
}

// NewFrame returns a new frame around the given primitive. The primitive's
// size will be changed to fit within this frame.
func ( Primitive) *Frame {
	 := NewBox()

	 := &Frame{
		Box:       ,
		primitive: ,
		top:       1,
		bottom:    1,
		header:    1,
		footer:    1,
		left:      1,
		right:     1,
	}

	.focus = 

	return 
}

// AddText adds text to the frame. Set "header" to true if the text is to appear
// in the header, above the contained primitive. Set it to false for it to
// appear in the footer, below the contained primitive. "align" must be one of
// the Align constants. Rows in the header are printed top to bottom, rows in
// the footer are printed bottom to top. Note that long text can overlap as
// different alignments will be placed on the same row.
func ( *Frame) ( string,  bool,  int,  tcell.Color) {
	.Lock()
	defer .Unlock()

	.text = append(.text, &frameText{
		Text:   ,
		Header: ,
		Align:  ,
		Color:  ,
	})
}

// Clear removes all text from the frame.
func ( *Frame) () {
	.Lock()
	defer .Unlock()

	.text = nil
}

// SetBorders sets the width of the frame borders as well as "header" and
// "footer", the vertical space between the header and footer text and the
// contained primitive (does not apply if there is no text).
func ( *Frame) (, , , , ,  int) {
	.Lock()
	defer .Unlock()

	.top, .bottom, .header, .footer, .left, .right = , , , , , 
}

// Draw draws this primitive onto the screen.
func ( *Frame) ( tcell.Screen) {
	if !.GetVisible() {
		return
	}

	.Box.Draw()

	.Lock()
	defer .Unlock()

	// Calculate start positions.
	, , ,  := .GetInnerRect()
	 :=  +  - 1
	 += .left
	 += .top
	 -= .bottom
	 -= .left + .right
	if  <= 0 ||  >=  {
		return // No space left.
	}

	// Draw text.
	var  [6]int // top-left, top-center, top-right, bottom-left, bottom-center, bottom-right.
	 := 
	 := 
	for ,  := range .text {
		// Where do we place this text?
		var  int
		if .Header {
			 =  + [.Align]
			[.Align]++
			if  >=  {
				continue
			}
			if +1 >  {
				 =  + 1
			}
		} else {
			 =  - [3+.Align]
			[3+.Align]++
			if  <=  {
				continue
			}
			if -1 <  {
				 =  - 1
			}
		}

		// Draw text.
		Print(, []byte(.Text), , , , .Align, .Color)
	}

	// Set the size of the contained primitive.
	if  >  {
		 =  + .header
	}
	if  <  {
		 =  - .footer
	}
	if  >  {
		return // No space for the primitive.
	}
	.primitive.SetRect(, , , +1-)

	// Finally, draw the contained primitive.
	.primitive.Draw()
}

// Focus is called when this primitive receives focus.
func ( *Frame) ( func( Primitive)) {
	.Lock()
	 := .primitive
	defer .Unlock()

	()
}

// HasFocus returns whether or not this primitive has focus.
func ( *Frame) () bool {
	.RLock()
	defer .RUnlock()

	,  := .primitive.(Focusable)
	if  {
		return .HasFocus()
	}
	return false
}

// MouseHandler returns the mouse handler for this primitive.
func ( *Frame) () func( MouseAction,  *tcell.EventMouse,  func( Primitive)) ( bool,  Primitive) {
	return .WrapMouseHandler(func( MouseAction,  *tcell.EventMouse,  func( Primitive)) ( bool,  Primitive) {
		if !.InRect(.Position()) {
			return false, nil
		}

		// Pass mouse events on to contained primitive.
		return .primitive.MouseHandler()(, , )
	})
}