package cps

import (
	"context"
	"testing"
)

type logger interface {
	Log(args ...interface{})
	Logf(format string, args ...interface{})
}

func (cmd *Command) cmp(o *Command, l logger) bool {
	if cmd.Raw != o.Raw {
		l.Logf("mismatched raw: have '%s', want '%s'", o.Raw, cmd.Raw)
		return false
	}

	if cmd.Command != o.Command {
		l.Logf("mismatched command: have '%s', want '%s'", o.Command, cmd.Command)
		return false
	}

	if cmd.Arg != o.Arg {
		l.Logf("mismatched arg: have '%s', want '%s'", o.Arg, cmd.Arg)
		return false
	}

	if len(cmd.Args) != len(o.Args) {
		l.Logf("mismatched arglen: have %d, want %d", len(o.Args), len(cmd.Args))
		return false
	}

	for i := range cmd.Args {
		if cmd.Args[i] != o.Args[i] {
			l.Logf("mismatched arg %d: have '%s', want '%s'", o.Args[i], cmd.Args[i])
			return false
		}
	}

	if len(cmd.Meta) != len(o.Meta) {
		l.Logf("mismatched metalen: have %d, want %d", len(o.Meta), len(cmd.Meta))
		return false
	}

	for k := range cmd.Meta {
		if cmd.Meta[k] != o.Meta[k] {
			l.Logf("mismatched meta for key '%s': have '%s', want '%s'",
				k, o.Meta[k], cmd.Meta[k])
			return false
		}
	}

	return true
}

func TestParseEmptyCommand(t *testing.T) {
	inputLine := "hello"
	expected := &Command{
		Context: context.Background(),
		Raw:     "hello",
		Command: "hello",
		Arg:     "",
		Args:    []string{},
		Meta:    map[string]string{},
	}

	cmd, err := ParseBackground(inputLine)
	if err != nil {
		t.Fatal(err)
	}

	if !expected.cmp(cmd, t) {
		t.FailNow()
	}
}

func TestParseNotEmptyCommand(t *testing.T) {
	inputLine := "hello world  this is a test"
	expected := &Command{
		Context: context.Background(),
		Raw:     "hello world  this is a test",
		Command: "hello",
		Arg:     "world  this is a test",
		Args: []string{
			"world",
			"this",
			"is",
			"a",
			"test",
		},
		Meta: map[string]string{},
	}

	cmd, err := ParseBackground(inputLine)
	if err != nil {
		t.Fatal(err)
	}

	if !expected.cmp(cmd, t) {
		t.FailNow()
	}
}