package container

import (
	"fyne.io/fyne/v2"
	intWidget "fyne.io/fyne/v2/internal/widget"
	"fyne.io/fyne/v2/widget"
)

// MultipleWindows is a container that handles multiple `InnerWindow` containers.
// Each inner window can be dragged, resized and the stacking will change when the title bar is tapped.
//
// Since: 2.5
type MultipleWindows struct {
	widget.BaseWidget

	Windows []*InnerWindow

	content *fyne.Container
}

// NewMultipleWindows creates a new `MultipleWindows` container to manage many inner windows.
// The initial window list is passed optionally to this constructor function.
// You can add new more windows to this container by calling `Add` or updating the `Windows`
// field and calling `Refresh`.
//
// Since: 2.5
func NewMultipleWindows(wins ...*InnerWindow) *MultipleWindows {
	m := &MultipleWindows{Windows: wins}
	m.ExtendBaseWidget(m)
	return m
}

func (m *MultipleWindows) Add(w *InnerWindow) {
	m.Windows = append(m.Windows, w)
	m.refreshChildren()
}

func (m *MultipleWindows) CreateRenderer() fyne.WidgetRenderer {
	m.content = New(&multiWinLayout{})
	m.refreshChildren()
	return widget.NewSimpleRenderer(intWidget.NewScroll(m.content))
}

func (m *MultipleWindows) Refresh() {
	m.refreshChildren()
	//	m.BaseWidget.Refresh()
}

func (m *MultipleWindows) raise(w *InnerWindow) {
	id := -1
	for i, ww := range m.Windows {
		if ww == w {
			id = i
			break
		}
	}
	if id == -1 {
		return
	}

	windows := append(m.Windows[:id], m.Windows[id+1:]...)
	m.Windows = append(windows, w)
	m.refreshChildren()
}

func (m *MultipleWindows) refreshChildren() {
	if m.content == nil {
		return
	}

	objs := make([]fyne.CanvasObject, len(m.Windows))
	for i, w := range m.Windows {
		objs[i] = w

		m.setupChild(w)
	}
	m.content.Objects = objs
	m.content.Refresh()
}

func (m *MultipleWindows) setupChild(w *InnerWindow) {
	w.OnDragged = func(ev *fyne.DragEvent) {
		w.Move(w.Position().Add(ev.Dragged))
	}
	w.OnResized = func(ev *fyne.DragEvent) {
		size := w.Size().Add(ev.Dragged)
		w.Resize(size.Max(w.MinSize()))
	}
	w.OnTappedBar = func() {
		m.raise(w)
	}
}

type multiWinLayout struct{}

func (m *multiWinLayout) Layout(objects []fyne.CanvasObject, _ fyne.Size) {
	for _, w := range objects { // update the windows so they have real size
		w.Resize(w.MinSize().Max(w.Size()))
	}
}

func (m *multiWinLayout) MinSize(_ []fyne.CanvasObject) fyne.Size {
	return fyne.Size{}
}
