package main

import (
	"bytes"
	"log"
	"red-green/door"
	"strings"
)

type TrackPanels struct {
	Panel  *door.Panel
	XPos   int
	YPos   int
	BColor []byte
}

// Find the Panel that was mouse clicked.
func FindPanel(m door.Mouse, panels []TrackPanels) int {
	for idx, p := range panels {
		hit, _, _ := p.Panel.Within(int(m.X), int(m.Y))
		if hit {
			return idx
		}
	}
	return -1
}

func panel_demo(d *door.Door) {
	var width int = 55
	var panel door.Panel = door.Panel{X: 5, Y: 5, Width: width, Style: door.DOUBLE, BorderColor: door.ColorText("CYAN ON BLUE"), Title: "[ Panel Demo ]"}
	var moveColor = door.ColorText("CYAN ON BLACK")
	var lineColor = door.ColorText("BRIGHT WHI ON BLUE")
	// Add lines to the panel
	for _, line := range []string{"The BBS Door Panel Demo", "(C) 2021 Red Green Software, https://red-green.com"} {
		if door.Unicode {
			line = strings.Replace(line, "(C)", "\u00a9", -1)
		}
		var l *door.Line = &door.Line{Text: bytes.NewBuffer([]byte(line)), Width: width, DefaultColor: lineColor}
		panel.Lines = append(panel.Lines, l)
	}
	panel.Lines = append(panel.Lines, panel.Spacer())
	panel.Lines = append(panel.Lines, &door.Line{Text: bytes.NewBuffer([]byte("Welcome to golang!")), Width: width, DefaultColor: lineColor})

	width = 10
	var single door.Panel = door.Panel{X: 6, Y: 12, Width: width, Style: door.SINGLE, BorderColor: door.ColorText("WHITE ON BLUE"), Title: "< Single >"}
	single.Lines = append(single.Lines, &door.Line{Text: bytes.NewBuffer([]byte("Example")), Width: width, DefaultColor: door.ColorText("WHI ON BLACK")})
	single.Lines = append(single.Lines, single.Spacer())
	single.Lines = append(single.Lines, &door.Line{Text: bytes.NewBuffer([]byte("More Text")), Width: width, DefaultColor: door.ColorText("BRI GREEN ON BLACK")})

	width = 15
	var double_single door.Panel = door.Panel{X: 26, Y: 12, Width: width, Style: door.DOUBLE_SINGLE, BorderColor: door.ColorText("BRI CYAN ON GREEN"), Title: "Double", TitleOffset: 3}
	double_single.Lines = append(double_single.Lines, &door.Line{Text: bytes.NewBuffer([]byte("Double / Single")), Width: width, DefaultColor: door.ColorText("BRI WHI ON GREEN")})
	double_single.Lines = append(double_single.Lines, double_single.Spacer())
	double_single.Lines = append(double_single.Lines, &door.Line{Text: bytes.NewBuffer([]byte("Some Other Text")), Width: width, DefaultColor: door.ColorText("BRI CYAN ON GREEN")})

	var single_double door.Panel = door.Panel{X: 46, Y: 12, Width: width, Style: door.SINGLE_DOUBLE, BorderColor: door.ColorText("BRI YELL ON RED")}
	single_double.Lines = append(single_double.Lines, &door.Line{Text: bytes.NewBuffer([]byte("Single / Double")), Width: width, DefaultColor: door.ColorText("BRI WHI ON RED")})
	single_double.Lines = append(single_double.Lines, single_double.Spacer())
	single_double.Lines = append(single_double.Lines, &door.Line{Text: bytes.NewBuffer([]byte("Text Goes Here ")), Width: width, DefaultColor: door.ColorText("BRI GREEN ON RED")})

	d.WriteA(door.Clrscr, panel.Output(), single.Output(), double_single.Output(), single_double.Output())
	d.WriteA(door.Goto(1, 20), door.Reset, "Use MOUSE to click/drag panels, Right-Click Exits, R to Reset, Q to quit...")

	var panels []TrackPanels = []TrackPanels{
		{&panel, panel.X, panel.Y, panel.BorderColor},
		{&single, single.X, single.Y, single.BorderColor},
		{&double_single, double_single.X, double_single.Y, single.BorderColor},
		{&single_double, single_double.X, single_double.Y, single_double.BorderColor}}

	var movingPanel *door.Panel
	var moveX, moveY int
	var panelColor []byte

	for {
		key, ex, err := d.WaitKey(door.Inactivity)
		if err != nil {
			return
		}
		if ex == door.MOUSE {
			m, ok := d.GetMouse()
			if ok {
				// Process Mouse Event
				if m.Button == 3 {
					// Exit on right click
					return
				}
				if m.Button == 1 {
					idx := FindPanel(m, panels)
					if idx != -1 {
						movingPanel = panels[idx].Panel
						panelColor = movingPanel.BorderColor
						moveX = int(m.X)
						moveY = int(m.Y)
					} else {
						continue
					}
					// Should we do something to the panel?  Yes!
					movingPanel.BorderColor = moveColor
					d.Update(movingPanel.Output())
				} else if m.Button == 4 {
					if movingPanel != nil {
						PR, PB := movingPanel.RightBottomPos()
						log.Printf("Panel (%d,%d) End(%d,%d) W %d, L %d\n", movingPanel.X, movingPanel.Y, PR, PB, movingPanel.Width, movingPanel.Length())
						// Ok, panel is move!
						d.Update(movingPanel.Clear())

						// Restore panel border
						movingPanel.BorderColor = panelColor

						// move panel
						movingPanel.X -= (moveX - int(m.X))
						movingPanel.Y -= (moveY - int(m.Y))

						// sanity checks
						if movingPanel.X < 1 {
							movingPanel.X = 1
						}

						// var edgeX bool
						if movingPanel.X+movingPanel.Width >= door.Width {
							movingPanel.X = door.Width - movingPanel.Width - 1
							// edgeX = true
						}
						if movingPanel.Y < 1 {
							movingPanel.Y = 1
						}

						// var edgeY bool
						if movingPanel.Y+movingPanel.Length() >= door.Height {
							movingPanel.Y = door.Height - movingPanel.Length() - 1
							// edgeY = true
						}

						PR, PB = movingPanel.RightBottomPos()
						log.Printf("Panel Now (%d,%d) End (%d,%d) %d, %d\n", movingPanel.X, movingPanel.Y, PR, PB, movingPanel.Width, movingPanel.Length()) //, edgeX, edgeY)
						// If panel is at the end of the screen -- it scrolls (syncterm)
						// This "fixes" it.  (Maybe a better way would be to not use last
						// line on the screen?)

						// Or another way:
						if PR == door.Width && PB == door.Height {
							movingPanel.X--
						}
						/*
							if edgeX && edgeY {
								movingPanel.X--
								log.Printf("Panel adjust X\n")
							}
						*/

						d.Update(movingPanel.Output())
					}
					movingPanel = nil
				}
			}
		} else {
			if (key == 'Q') || (key == 'q') || (key == '\x1b') {
				return
			}

			if (key == 'R') || (key == 'r') {
				for _, p := range panels {
					d.Update(p.Panel.Clear())
				}
				for _, p := range panels {
					p.Panel.X = p.XPos
					p.Panel.Y = p.YPos
					p.Panel.BorderColor = p.BColor
					d.Update(p.Panel.Output())
				}
			}
			if key == '0' {
				d.Write(panels[0].Panel.GotoEnd())
			}
			if key == '1' {
				d.Write(panels[1].Panel.GotoEnd())
			}

		}
	}
}