package cview

import (
	
	

	
)

// Slider is a progress bar which may be modified via keyboard and mouse.
type Slider struct {
	*ProgressBar

	// The text to be displayed before the slider.
	label []byte

	// The screen width of the label area. A value of 0 means use the width of
	// the label text.
	labelWidth int

	// The label color.
	labelColor tcell.Color

	// The label color when focused.
	labelColorFocused tcell.Color

	// The background color of the input area.
	fieldBackgroundColor tcell.Color

	// The background color of the input area when focused.
	fieldBackgroundColorFocused tcell.Color

	// The text color of the input area.
	fieldTextColor tcell.Color

	// The text color of the input area when focused.
	fieldTextColorFocused tcell.Color

	// The amount to increment by when modified via keyboard.
	increment int

	// Set to true when mouse dragging is in progress.
	dragging bool

	// An optional function which is called when the user changes the value of
	// this slider.
	changed func(value int)

	// An optional function which is called when the user indicated that they
	// are done entering text. The key which was pressed is provided (tab,
	// shift-tab, or escape).
	done func(tcell.Key)

	// A callback function set by the Form class and called when the user leaves
	// this form item.
	finished func(tcell.Key)

	sync.RWMutex
}

// NewSlider returns a new slider.
func () *Slider {
	 := &Slider{
		ProgressBar:                 NewProgressBar(),
		increment:                   10,
		labelColor:                  Styles.SecondaryTextColor,
		fieldBackgroundColor:        Styles.MoreContrastBackgroundColor,
		fieldBackgroundColorFocused: Styles.ContrastBackgroundColor,
		fieldTextColor:              Styles.PrimaryTextColor,
		labelColorFocused:           ColorUnset,
		fieldTextColorFocused:       ColorUnset,
	}
	return 
}

// SetLabel sets the text to be displayed before the input area.
func ( *Slider) ( string) {
	.Lock()
	defer .Unlock()

	.label = []byte()
}

// GetLabel returns the text to be displayed before the input area.
func ( *Slider) () string {
	.RLock()
	defer .RUnlock()

	return string(.label)
}

// SetLabelWidth sets the screen width of the label. A value of 0 will cause the
// primitive to use the width of the label string.
func ( *Slider) ( int) {
	.Lock()
	defer .Unlock()

	.labelWidth = 
}

// SetLabelColor sets the color of the label.
func ( *Slider) ( tcell.Color) {
	.Lock()
	defer .Unlock()

	.labelColor = 
}

// SetLabelColorFocused sets the color of the label when focused.
func ( *Slider) ( tcell.Color) {
	.Lock()
	defer .Unlock()

	.labelColorFocused = 
}

// SetFieldBackgroundColor sets the background color of the input area.
func ( *Slider) ( tcell.Color) {
	.Lock()
	defer .Unlock()

	.fieldBackgroundColor = 
}

// SetFieldBackgroundColorFocused sets the background color of the input area when focused.
func ( *Slider) ( tcell.Color) {
	.Lock()
	defer .Unlock()

	.fieldBackgroundColorFocused = 
}

// SetFieldTextColor sets the text color of the input area.
func ( *Slider) ( tcell.Color) {
	.Lock()
	defer .Unlock()

	.fieldTextColor = 
}

// SetFieldTextColorFocused sets the text color of the input area when focused.
func ( *Slider) ( tcell.Color) {
	.Lock()
	defer .Unlock()

	.fieldTextColorFocused = 
}

// GetFieldHeight returns the height of the field.
func ( *Slider) () int {
	return 1
}

// GetFieldWidth returns this primitive's field width.
func ( *Slider) () int {
	return 0
}

// SetIncrement sets the amount the slider is incremented by when modified via
// keyboard.
func ( *Slider) ( int) {
	.Lock()
	defer .Unlock()

	.increment = 
}

// SetChangedFunc sets a handler which is called when the value of this slider
// was changed by the user. The handler function receives the new value.
func ( *Slider) ( func( int)) {
	.Lock()
	defer .Unlock()

	.changed = 
}

// SetDoneFunc sets a handler which is called when the user is done using the
// slider. The callback function is provided with the key that was pressed,
// which is one of the following:
//
//   - KeyEscape: Abort text input.
//   - KeyTab: Move to the next field.
//   - KeyBacktab: Move to the previous field.
func ( *Slider) ( func( tcell.Key)) {
	.Lock()
	defer .Unlock()

	.done = 
}

// SetFinishedFunc sets a callback invoked when the user leaves this form item.
func ( *Slider) ( func( tcell.Key)) {
	.Lock()
	defer .Unlock()

	.finished = 
}

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

	.Box.Draw()
	 := .GetFocusable().HasFocus()

	.Lock()

	// Select colors
	 := .labelColor
	 := .fieldBackgroundColor
	 := .fieldTextColor
	if  {
		if .labelColorFocused != ColorUnset {
			 = .labelColorFocused
		}
		if .fieldBackgroundColorFocused != ColorUnset {
			 = .fieldBackgroundColorFocused
		}
		if .fieldTextColorFocused != ColorUnset {
			 = .fieldTextColorFocused
		}
	}

	// Prepare.
	, , ,  := .GetInnerRect()
	 :=  + 
	if  < 1 ||  <=  {
		.Unlock()
		return
	}

	// Draw label.
	if len(.label) > 0 {
		if .vertical {
			--

			// TODO draw label on bottom
		} else {
			if .labelWidth > 0 {
				 := .labelWidth
				if  > - {
					 =  - 
				}
				Print(, []byte(.label), , , , AlignLeft, )
				 +=  + 1
				 -=  + 1
			} else {
				,  := Print(, []byte(.label), , , -, AlignLeft, )
				 +=  + 1
				 -=  + 1
			}
		}
	}

	// Draw slider.
	.Unlock()
	.ProgressBar.SetRect(, , , )
	.ProgressBar.SetEmptyColor()
	.ProgressBar.SetFilledColor()
	.ProgressBar.Draw()
}

// InputHandler returns the handler for this primitive.
func ( *Slider) () func( *tcell.EventKey,  func( Primitive)) {
	return .WrapInputHandler(func( *tcell.EventKey,  func( Primitive)) {
		if HitShortcut(, Keys.Cancel, Keys.MovePreviousField, Keys.MoveNextField) {
			if .done != nil {
				.done(.Key())
			}
			if .finished != nil {
				.finished(.Key())
			}
			return
		}

		 := .progress

		if HitShortcut(, Keys.MoveFirst, Keys.MoveFirst2) {
			.SetProgress(0)
		} else if HitShortcut(, Keys.MoveLast, Keys.MoveLast2) {
			.SetProgress(.max)
		} else if HitShortcut(, Keys.MoveUp, Keys.MoveUp2, Keys.MoveRight, Keys.MoveRight2, Keys.MovePreviousField) {
			.AddProgress(.increment)
		} else if HitShortcut(, Keys.MoveDown, Keys.MoveDown2, Keys.MoveLeft, Keys.MoveLeft2, Keys.MoveNextField) {
			.AddProgress(.increment * -1)
		}

		if .progress !=  && .changed != nil {
			.changed(.progress)
		}
	})
}

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

		// Process mouse event.
		if  == MouseLeftClick {
			()
			 = true
		}

		 := func() {
			if !.ProgressBar.InRect(, ) {
				.dragging = false
				return
			}

			, , ,  := .GetInnerRect()
			var ,  int
			if .ProgressBar.vertical {
				 = ( - 1) - ( - )
				 =  - 1
			} else {
				 =  - 
				 =  - 1
			}
			 := int(math.Floor(float64(.max) * (float64() / float64())))
			if  != .progress {
				.SetProgress()
				if .changed != nil {
					.changed(.progress)
				}
			}
		}

		// Handle dragging. Clicks are implicitly handled by this logic.
		switch  {
		case MouseLeftDown:
			()
			 = true
			 = 
			.dragging = true

			()
		case MouseMove:
			if .dragging {
				 = true
				 = 

				()
			}
		case MouseLeftUp:
			if .dragging {
				 = true
				.dragging = false

				()
			}
		}

		return
	})
}