// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.

package target

import (
_	"context"
	"encoding/json"
	"github.com/stretchr/testify/assert"
	"net/url"
	"testing"
	"decl/internal/resource"
)

type MockDocTarget struct {
	InjectType func() string
	InjectEmitResources func(documents []*resource.Document, filter resource.ResourceSelector) error
}

func (m *MockDocTarget) Type() string { return m.InjectType() }
func (m *MockDocTarget) EmitResources(documents []*resource.Document, filter resource.ResourceSelector) error { return m.InjectEmitResources(documents, filter) }

func NewFooDocTarget() DocTarget {
	return &MockDocTarget{
		InjectType: func() string { return "foo" },
		InjectEmitResources: func(documents []*resource.Document, filter resource.ResourceSelector) error { return nil },
	}
}

func NewMockFileDocTarget() DocTarget {
	return &MockDocTarget{
		InjectType: func() string { return "file" },
		InjectEmitResources: func(documents []*resource.Document, filter resource.ResourceSelector) error { return nil },
	}
}

func TestNewTargetTypes(t *testing.T) {
	targetTypes := NewTypes()
	assert.NotNil(t, targetTypes)
}

func TestNewTargetTypesRegister(t *testing.T) {
	m := NewFooDocTarget()

	targetTypes := NewTypes()
	assert.NotNil(t, targetTypes)

	targetTypes.Register([]string{"foo"}, func(*url.URL) DocTarget { return m })

	r, e := targetTypes.New("foo://")
	assert.Nil(t, e)
	assert.Equal(t, m, r)
}

func TestResourceTypesFromURI(t *testing.T) {
	m := NewFooDocTarget()

	targetTypes := NewTypes()
	assert.NotNil(t, targetTypes)

	targetTypes.Register([]string{"foo"}, func(*url.URL) DocTarget { return m })

	r, e := targetTypes.New("foo://bar")
	assert.Nil(t, e)
	assert.Equal(t, m, r)
}

func TestResourceTypesHasType(t *testing.T) {
	m := NewFooDocTarget()

	targetTypes := NewTypes()
	assert.NotNil(t, targetTypes)

	targetTypes.Register([]string{"foo"}, func(*url.URL) DocTarget { return m })

	assert.True(t, targetTypes.Has("foo"))
}

func TestDocTargetTypeName(t *testing.T) {
	TargetTypes.Register([]string{"file"}, func(*url.URL) DocTarget { return NewMockFileDocTarget() })

	type fDocTargetName struct {
		Name TypeName `json:"type"`
	}
	fTypeName := &fDocTargetName{}
	jsonType := `{ "type": "file" }`
	e := json.Unmarshal([]byte(jsonType), &fTypeName)
	assert.Nil(t, e)
	assert.Equal(t, "file", string(fTypeName.Name))
}
