package imgui

// #include "stdlib.h"
// #include "TextEditorWrapper.h"
import "C"
import "unsafe"

type LanguageDefinition uintptr

func NewLanguageDefinition() LanguageDefinition {
	handle := C.IggNewLanguageDef()
	return LanguageDefinition(handle)
}

func (ld LanguageDefinition) handle() C.IggTextEditorLanguageDefinition {
	return C.IggTextEditorLanguageDefinition(ld)
}

func (ld LanguageDefinition) SetName(name string) {
	nameArg, nameDeleter := wrapString(name)
	defer nameDeleter()

	C.IggTextEditorLDSetName(ld.handle(), nameArg)
}

func (ld LanguageDefinition) SetKeywords(keywords []string) {
	keywordsArg := make([]*C.char, len(keywords))
	for i, k := range keywords {
		kArg, kDeleter := wrapString(k)
		defer kDeleter()
		keywordsArg[i] = kArg
	}

	C.IggTextEditorLDSetKeywords(ld.handle(), &keywordsArg[0], C.int(len(keywords)))
}

type TextEditor uintptr

func NewTextEditor() TextEditor {
	handle := C.IggNewTextEditor()
	return TextEditor(handle)
}

func (t TextEditor) handle() C.IggTextEditor {
	return C.IggTextEditor(t)
}

func (t TextEditor) Render(title string, size Vec2, border bool) {
	titleArg, titleFn := wrapString(title)
	defer titleFn()

	sizeArg, _ := size.wrapped()

	C.IggTextEditorRender(t.handle(), titleArg, sizeArg, castBool(border))
}

func (t TextEditor) SetShowWhitespaces(show bool) {
	C.IggTextEditorSetShowWhitespaces(t.handle(), castBool(show))
}

func (t TextEditor) SetTabSize(size int) {
	C.IggTextEditorSetTabSize(t.handle(), C.int(size))
}

func (t TextEditor) InsertText(text string) {
	textArg, textFn := wrapString(text)
	defer textFn()

	C.IggTextEditorInsertText(t.handle(), textArg)
}

func (t TextEditor) SetText(text string) {
	textArg, textFn := wrapString(text)
	defer textFn()

	C.IggTextEditorSetText(t.handle(), textArg)
}

func (t TextEditor) GetText() string {
	str := C.IggTextEditorGetText(t.handle())
	defer C.free(unsafe.Pointer(str))

	return C.GoString(str)
}

func (t TextEditor) GetWordUnderCursor() string {
	str := C.IggTextEditorGetWordUnderCursor(t.handle())
	defer C.free(unsafe.Pointer(str))

	return C.GoString(str)
}

func (t TextEditor) HasSelection() bool {
	return C.IggTextEditorHasSelection(t.handle()) != 0
}

func (t TextEditor) GetSelectedText() string {
	str := C.IggTextEditorGetSelectedText(t.handle())
	defer C.free(unsafe.Pointer(str))

	return C.GoString(str)
}

func (t TextEditor) GetCurrentLineText() string {
	str := C.IggTextEditorGetCurrentLineText(t.handle())
	defer C.free(unsafe.Pointer(str))

	return C.GoString(str)
}

func (t TextEditor) IsTextChanged() bool {
	return C.IggTextEditorIsTextChanged(t.handle()) != 0
}

func (t TextEditor) GetScreenCursorPos() (int, int) {
	var column int
	var line int

	C.IggTextEditorGetScreenCursorPos(t.handle(), (*C.int)(unsafe.Pointer(&column)), (*C.int)(unsafe.Pointer(&line)))

	return column, line
}

func (t TextEditor) GetCursorPos() (int, int) {
	var column int
	var line int

	C.IggTextEditorGetCursorPos(t.handle(), (*C.int)(unsafe.Pointer(&column)), (*C.int)(unsafe.Pointer(&line)))

	return column, line
}

func (t TextEditor) SetCursorPos(line, column int) {
	C.IggTextEditorSetCursorPos(t.handle(), (C.int)(column), (C.int)(line))
}

func (t TextEditor) GetSelectionStart() (int, int) {
	var column int
	var line int

	C.IggTextEditorGetSelectionStart(t.handle(), (*C.int)(unsafe.Pointer(&column)), (*C.int)(unsafe.Pointer(&line)))

	return column, line
}

func (t TextEditor) SetLanguageDefinition(ld LanguageDefinition) {
	C.IggTextEditorSetLanguageDefinition(t.handle(), ld.handle())
}

func (t TextEditor) SetLanguageDefinitionSQL() {
	C.IggTextEditorSetLanguageDefinitionSQL(t.handle())
}

func (t TextEditor) SetLanguageDefinitionCPP() {
	C.IggTextEditorSetLanguageDefinitionCPP(t.handle())
}

func (t TextEditor) SetLanguageDefinitionC() {
	C.IggTextEditorSetLanguageDefinitionC(t.handle())
}

func (t TextEditor) SetLanguageDefinitionLua() {
	C.IggTextEditorSetLanguageDefinitionLua(t.handle())
}

type ErrorMarkers uintptr

func NewErrorMarkers() ErrorMarkers {
	handle := C.IggTextEditorNewErrorMarkers()
	return ErrorMarkers(handle)
}

func (e ErrorMarkers) handle() C.IggTextEditorErrorMarkers {
	return C.IggTextEditorErrorMarkers(e)
}

func (e ErrorMarkers) Insert(pos int, errMsg string) {
	errMsgArg, errMsgFn := wrapString(errMsg)
	defer errMsgFn()

	C.IggTextEditorErrorMarkersInsert(e.handle(), C.int(pos), errMsgArg)
}

func (e ErrorMarkers) Clear() {
	C.IggTextEditorErrorMarkersClear(e.handle())
}

func (e ErrorMarkers) Size() uint {
	return uint(C.IggTextEditorErrorMarkersSize(e.handle()))
}

func (t TextEditor) SetErrorMarkers(markers ErrorMarkers) {
	C.IggTextEditorSetErrorMarkers(t.handle(), markers.handle())
}

func (t TextEditor) Copy() {
	C.IggTextEditorCopy(t.handle())
}

func (t TextEditor) Cut() {
	C.IggTextEditorCut(t.handle())
}

func (t TextEditor) Paste() {
	C.IggTextEditorPaste(t.handle())
}

func (t TextEditor) Delete() {
	C.IggTextEditorDelete(t.handle())
}

func (t TextEditor) SelectWordUnderCursor() {
	C.IggTextEditorSelectWordUnderCursor(t.handle())
}

func (t TextEditor) SelectAll() {
	C.IggTextEditorSelectAll(t.handle())
}

func (t TextEditor) SetHandleKeyboardInputs(b bool) {
	val := 0
	if b {
		val = 1
	}
	C.IggTextEditorSetHandleKeyboardInputs(t.handle(), C.int(val))
}
