package main

import (
	"fmt"
	"image"
	"unsafe"

	"github.com/ivanizag/izapple2"
	"github.com/ivanizag/izapple2/screen"

	"github.com/pkg/profile"
	"github.com/veandco/go-sdl2/sdl"
)

func main() {
	a, err := izapple2.CreateConfiguredApple()
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}
	if a != nil {
		if a.IsProfiling() {
			// See the log with:
			//    go tool pprof --pdf ~/go/bin/izapple2sdl /tmp/profile329536248/cpu.pprof > profile.pdf
			defer profile.Start().Stop()
		}

		sdlRun(a)
	}
}

func sdlRun(a *izapple2.Apple2) {

	window, renderer, err := sdl.CreateWindowAndRenderer(4*40*7+8, 4*24*8,
		sdl.WINDOW_SHOWN)
	if err != nil {
		panic("Failed to create window")
	}
	window.SetResizable(true)

	defer window.Destroy()
	defer renderer.Destroy()

	title := "iz-" + a.Name + " (F1 for help)"
	window.SetTitle(title)

	sdl.SetHint(sdl.HINT_RENDER_SCALE_QUALITY, "best")

	kp := newSDLKeyBoard(a)

	s := newSDLSpeaker()
	s.start()
	a.SetSpeakerProvider(s)

	j := newSDLJoysticks(true)
	a.SetJoysticksProvider(j)

	m := newSDLMouse()
	a.SetMouseProvider(m)

	go a.Run()

	var x int32
	paused := false
	running := true
	for running {
		for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
			switch t := event.(type) {
			case *sdl.QuitEvent:
				a.SendCommand(izapple2.CommandKill)
				running = false
			case *sdl.KeyboardEvent:
				kp.putKey(t)
				j.putKey(t)
			case *sdl.TextInputEvent:
				kp.putText(t.GetText())
			case *sdl.JoyAxisEvent:
				j.putAxisEvent(t)
			case *sdl.JoyButtonEvent:
				j.putButtonEvent(t)
			case *sdl.MouseMotionEvent:
				w, h := window.GetSize()
				j.putMouseMotionEvent(t, w, h)
				m.putMouseMotionEvent(t, w, h)
				x = t.X
			case *sdl.MouseButtonEvent:
				j.putMouseButtonEvent(t)
				m.putMouseButtonEvent(t)
			case *sdl.DropEvent:
				switch t.Type {
				case sdl.DROPFILE:
					w, _ := window.GetSize()
					drive := int(2 * x / w)
					fmt.Printf("Loading '%s' in drive %v\n", t.File, drive+1)
					a.SendLoadDisk(drive, t.File)
				}
			}
		}

		if paused != a.IsPaused() {
			if a.IsPaused() {
				window.SetTitle(title + " - PAUSED!")
			} else {
				window.SetTitle(title)
			}
			paused = a.IsPaused()
		}

		if !a.IsPaused() {
			var img *image.RGBA
			if kp.showHelp {
				img = screen.SnapshotMessageGenerator(a, helpMessage)
			} else if kp.showCharGen {
				img = screen.SnapshotCharacterGenerator(a, kp.showAltText)
				window.SetTitle(fmt.Sprintf("%v character map", a.Name))
			} else if kp.showPages {
				img = screen.SnapshotParts(a, kp.screenMode)
				window.SetTitle(fmt.Sprintf("%v %v %vx%v", a.Name, screen.VideoModeName(a), img.Rect.Dx()/2, img.Rect.Dy()/2))
			} else {
				img = screen.Snapshot(a, kp.screenMode)
			}
			if img != nil {
				surface, err := sdl.CreateRGBSurfaceFrom(unsafe.Pointer(&img.Pix[0]),
					int32(img.Bounds().Dx()), int32(img.Bounds().Dy()),
					32, 4*img.Bounds().Dx(),
					0x0000ff, 0x0000ff00, 0x00ff0000, 0xff000000)
				// Valid for little endian. Should we reverse for big endian?
				// 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff)

				if err != nil {
					panic(err)
				}

				texture, err := renderer.CreateTextureFromSurface(surface)
				if err != nil {
					panic(err)
				}

				renderer.Clear()
				renderer.Copy(texture, nil, nil)
				renderer.Present()
				surface.Free()
				texture.Destroy()
			}
		}
		sdl.Delay(1000 / 30)
	}

}

var helpMessage = `

        F1: Show/Hide help
   Ctrl-F2: Reset
        F5: Fast/Normal speed
   Ctrl-F5: Show speed
        F6: Next screen mode
        F7: Show/Hide pages
       F10: Next character set
  Ctrl-F10: Show/Hide character set
 Shift-F10: Show/Hide alternate text
       F11: Show/Hide CPU trace
       F12: Save screen snapshot
	 Pause: Pause the emulation

 Drop a file on the left or right
 side of the window to load a disk

 Run izapple2 -h for more options

 More info at
   https://github.com/ivanizag/izapple2
`

///////////////////////////////////////
