package jdenticon

import (
	"context"
	"fmt"
)

// Package-level convenience functions for simple use cases.
// These wrap the Generator API for easy one-off identicon generation.

var (
	// defaultGenerator is a package-level generator instance for convenience functions.
	// It uses default configuration with a small cache for better performance.
	defaultGenerator *Generator
)

func init() {
	// Initialize the default generator with a small cache
	var err error
	defaultGenerator, err = NewGeneratorWithCacheSize(50)
	if err != nil {
		// Fall back to no caching if cache creation fails
		defaultGenerator, _ = NewGenerator()
	}
}

// Generate creates an identicon using the default configuration with context support.
// The context can be used to set timeouts or cancel generation.
//
// This is a convenience function equivalent to:
//
//	generator := jdenticon.NewGenerator()
//	icon := generator.Generate(ctx, input, size)
//
// For more control over configuration or caching, use Generator directly.
func Generate(ctx context.Context, input string, size int) (*Icon, error) {
	// Apply input validation using default configuration
	config := DefaultConfig()
	if err := validateInputs(input, size, config); err != nil {
		return nil, err
	}

	if defaultGenerator == nil {
		return nil, NewErrGenerationFailed(input, size, fmt.Errorf("default generator not initialized"))
	}
	return defaultGenerator.Generate(ctx, input, size)
}

// ToSVG generates an identicon and returns it as an SVG string with context support.
// The context can be used to set timeouts or cancel generation.
//
// This is a convenience function that uses default configuration.
func ToSVG(ctx context.Context, input string, size int) (string, error) {
	return ToSVGWithConfig(ctx, input, size, DefaultConfig())
}

// ToPNG generates an identicon and returns it as PNG bytes with context support.
// The context can be used to set timeouts or cancel generation.
//
// This is a convenience function that uses default configuration with dynamic supersampling
// to ensure the effective size stays within safe limits while maximizing quality.
func ToPNG(ctx context.Context, input string, size int) ([]byte, error) {
	// Start with default configuration
	config := DefaultConfig()

	// Apply dynamic supersampling to respect size limits
	if maxSize := config.effectiveMaxIconSize(); maxSize != -1 {
		effectiveSize := size * config.PNGSupersampling
		if effectiveSize > maxSize {
			// Calculate the maximum safe supersampling factor
			newSupersampling := maxSize / size
			if newSupersampling >= 1 {
				config.PNGSupersampling = newSupersampling
			} else {
				// Even 1x supersampling would exceed limits, let validation catch this
				config.PNGSupersampling = 1
			}
		}
	}

	return ToPNGWithConfig(ctx, input, size, config)
}

// ToSVGWithConfig generates an identicon with custom configuration and returns it as an SVG string.
func ToSVGWithConfig(ctx context.Context, input string, size int, config Config) (string, error) {
	// Validate inputs using the provided configuration
	if err := validateInputs(input, size, config); err != nil {
		return "", err
	}

	// Validate the configuration itself
	if err := config.Validate(); err != nil {
		return "", err
	}

	generator, err := NewGeneratorWithConfig(config, 1) // Minimal caching for one-off usage
	if err != nil {
		return "", err
	}

	icon, err := generator.Generate(ctx, input, size)
	if err != nil {
		return "", err
	}

	return icon.ToSVG()
}

// ToPNGWithConfig generates an identicon with custom configuration and returns it as PNG bytes.
func ToPNGWithConfig(ctx context.Context, input string, size int, config Config) ([]byte, error) {
	// Validate inputs using the provided configuration
	if err := validateInputs(input, size, config); err != nil {
		return nil, err
	}

	// Validate the configuration itself
	if err := config.Validate(); err != nil {
		return nil, err
	}

	// Validate PNG-specific effective size (size * supersampling)
	if err := validatePNGSize(size, config); err != nil {
		return nil, err
	}

	generator, err := NewGeneratorWithConfig(config, 1) // Minimal caching for one-off usage
	if err != nil {
		return nil, err
	}

	icon, err := generator.Generate(ctx, input, size)
	if err != nil {
		return nil, err
	}

	return icon.ToPNG()
}
