package scim

import (
	"sync"

	scimjson "github.com/imulab/go-scim/pkg/v2/json"
	"github.com/imulab/go-scim/pkg/v2/service"
	"github.com/imulab/go-scim/pkg/v2/spec"
)

var (
	registerScimSchemaOnce sync.Once
)

func ListSchemas() (*service.QueryResponse, error) {
	var resources []scimjson.Serializable
	if err := spec.Schemas().ForEachSchema(func(schema *spec.Schema) error {
		if schema.ID() == spec.CoreSchemaId {
			return nil
		}
		resources = append(resources, scimjson.SchemaToSerializable(schema))
		return nil
	}); err != nil {
		return nil, err
	}

	// generate schema result
	result := &service.QueryResponse{
		TotalResults: len(resources),
		StartIndex:   1,
		ItemsPerPage: len(resources),
		Resources:    resources,
	}

	return result, nil
}

func GetSchemaByID(id string) (scimjson.Serializable, error) {
	cache := map[string]scimjson.Serializable{}
	_ = spec.Schemas().ForEachSchema(func(schema *spec.Schema) error {
		if schema.ID() == spec.CoreSchemaId {
			return nil
		}
		serializable := scimjson.SchemaToSerializable(schema)
		cache[schema.ID()] = serializable
		return nil
	})

	serializable, ok := cache[id]
	if !ok {
		return nil, nil
	}
	return serializable, nil
}

func EnsureSchemaRegistered() {
	registerScimSchemaOnce.Do(func() {
		schemas, err := ParseSchemas()
		if err != nil {
			panic(err)
		}
		for i := range schemas {
			schema := schemas[i]
			spec.Schemas().Register(&schema)
		}
	})
}
