// Copyright 2016 The Walk Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build windows

package walk

import (
	"unsafe"
)

import (
	"github.com/lxn/win"
)

type SplitButton struct {
	Button
	menu *Menu
}

func NewSplitButton(parent Container) (*SplitButton, error) {
	sb := new(SplitButton)

	var disposables Disposables
	defer disposables.Treat()

	if err := InitWidget(
		sb,
		parent,
		"BUTTON",
		win.WS_TABSTOP|win.WS_VISIBLE|win.BS_SPLITBUTTON,
		0); err != nil {
		return nil, err
	}
	disposables.Add(sb)

	sb.Button.init()

	menu, err := NewMenu()
	if err != nil {
		return nil, err
	}
	disposables.Add(menu)
	menu.window = sb
	sb.menu = menu

	sb.GraphicsEffects().Add(InteractionEffect)
	sb.GraphicsEffects().Add(FocusEffect)

	disposables.Spare()

	return sb, nil
}

func (sb *SplitButton) Dispose() {
	sb.Button.Dispose()

	sb.menu.Dispose()
}

func (sb *SplitButton) ImageAboveText() bool {
	return sb.hasStyleBits(win.BS_TOP)
}

func (sb *SplitButton) SetImageAboveText(value bool) error {
	if err := sb.ensureStyleBits(win.BS_TOP, value); err != nil {
		return err
	}

	// We need to set the image again, or Windows will fail to calculate the
	// button control size correctly.
	return sb.SetImage(sb.image)
}

func (sb *SplitButton) Menu() *Menu {
	return sb.menu
}

func (sb *SplitButton) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) uintptr {
	switch msg {
	case win.WM_NOTIFY:
		switch ((*win.NMHDR)(unsafe.Pointer(lParam))).Code {
		case win.BCN_DROPDOWN:
			dd := (*win.NMBCDROPDOWN)(unsafe.Pointer(lParam))

			p := win.POINT{dd.RcButton.Left, dd.RcButton.Bottom}

			win.ClientToScreen(sb.hWnd, &p)

			win.TrackPopupMenuEx(
				sb.menu.hMenu,
				win.TPM_NOANIMATION,
				p.X,
				p.Y,
				sb.hWnd,
				nil)
			return 0
		}
	}

	return sb.Button.WndProc(hwnd, msg, wParam, lParam)
}
