package main

import (
	"reflect"
	"strings"
	"testing"

	"hakurei.app/check"
	"hakurei.app/fhs"
	"hakurei.app/hst"
)

func TestParse(t *testing.T) {
	t.Parallel()

	base := fhs.AbsProc.Append("nonexistent")
	testCases := []struct {
		name string
		data string
		want *hst.Config
		err  error
	}{
		{"com.discordapp.Discord", `nonfree:8
exec Discord --ozone-platform-hint=wayland

gpu
wayland
dbus
system_bus
pipewire
userns
net
mapuid

share_runtime
share_tmpdir

group media_rw
env ELECTRON_TRASH=gio
rw "/sdcard"
; remove before reusing
ro "/bin\x00/.hakurei/bin"

talk org.kde.StatusNotifierWatcher
talk com.canonical.AppMenu.Registrar
talk com.canonical.indicator.application
talk com.canonical.Unity
`, &hst.Config{
			Identity:    8,
			ID:          "com.discordapp.Discord",
			Enablements: new(hst.EWayland | hst.EDBus | hst.EPipeWire),
			Groups:      []string{"media_rw"},

			SessionBus: &hst.BusConfig{
				Talk: []string{
					"org.kde.StatusNotifierWatcher",
					"com.canonical.AppMenu.Registrar",
					"com.canonical.indicator.application",
					"com.canonical.Unity",
				},
				Own: []string{
					"com.discordapp.Discord.*",
					"org.mpris.MediaPlayer2.com.discordapp.Discord.*",
				},
				Filter: true,
			},
			SystemBus: &hst.BusConfig{Filter: true},

			Container: &hst.ContainerConfig{
				Env: map[string]string{
					"ELECTRON_TRASH": "gio",
				},
				Filesystem: []hst.FilesystemConfigJSON{
					{FilesystemConfig: &hst.FSOverlay{
						Target: fhs.AbsRoot,
						Lower: []*check.Absolute{
							base.Append("initial"),
						},
						Upper: base.Append("template", "nonfree"),
					}},
					{FilesystemConfig: &hst.FSBind{
						Target: hst.AbsPrivateTmp.Append("home"),
						Source: base.Append("state", "com.discordapp.Discord"),
						Write:  true,
						Ensure: true,
					}},

					{FilesystemConfig: &hst.FSEphemeral{
						Target: fhs.AbsVar.Append("tmp"),
						Write:  true,
						Perm:   01777,
					}},

					{FilesystemConfig: &hst.FSBind{
						Source: check.MustAbs("/sdcard"),
						Write:  true,
					}},
					{FilesystemConfig: &hst.FSBind{
						Target: check.MustAbs("/.hakurei/bin"),
						Source: check.MustAbs("/bin"),
					}},

					{FilesystemConfig: &hst.FSBind{
						Source:   fhs.AbsDev.Append("dri"),
						Device:   true,
						Optional: true,
					}},
				},

				Username: "chronos",
				Shell:    fhs.AbsRoot.Append("bin", "zsh"),
				Home:     hst.AbsPrivateTmp.Append("home"),
				Path:     fhs.AbsRoot.Append("bin", "zsh"),
				Args: []string{
					"zsh", "-c",
					"exec Discord --ozone-platform-hint=wayland",
					"",
				},

				Flags: hst.FCoverRun | hst.FUserns | hst.FHostNet | hst.FMapRealUID |
					hst.FShareRuntime | hst.FShareTmpdir,
			},
		}, nil},
	}
	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			t.Parallel()

			got, err := parse(
				tc.name,
				base,
				strings.NewReader(tc.data),
				nil,
			)

			if !reflect.DeepEqual(err, tc.err) {
				t.Errorf("parse: error = %v, want %v", err, tc.err)
			}
			if err != nil {
				return
			}

			if !reflect.DeepEqual(got, tc.want) {
				t.Errorf("parse: %#v, want %#v", got, tc.want)
			}
		})
	}
}
