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

package source

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

type MockDocSource struct {
	InjectType func() string
	InjectExtractResources func(filter ResourceSelector) ([]*resource.Document, error)
}

func (m *MockDocSource) Type() string { return m.InjectType() }
func (m *MockDocSource) ExtractResources(filter ResourceSelector) ([]*resource.Document, error) { return m.InjectExtractResources(filter) }

func NewFooDocSource() DocSource {
	return &MockDocSource{
		InjectType: func() string { return "foo" },
		InjectExtractResources: func(filter ResourceSelector) ([]*resource.Document, error) { return nil,nil },
	}
}

func NewFileDocSource() DocSource {
	return &MockDocSource{
		InjectType: func() string { return "file" },
		InjectExtractResources: func(filter ResourceSelector) ([]*resource.Document, error) { return nil,nil },
	}
}

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

func TestNewSourceTypesRegister(t *testing.T) {
	m := NewFooDocSource()

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

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

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

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

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

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

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

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

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

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

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

func TestDocSourceTypeName(t *testing.T) {
	SourceTypes.Register([]string{"file"}, func(*url.URL) DocSource { return NewFileDocSource() })

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