// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package internal // import "go.opentelemetry.io/collector/internal/cmd/pdatagen/internal"

import (
	"os"
	"path/filepath"
	"strings"
)

const header = `// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

// Code generated by "internal/cmd/pdatagen/main.go". DO NOT EDIT.
// To regenerate this file run "make genpdata".`

// AllPackages is a list of all packages that needs to be generated.
var AllPackages = []*Package{
	pcommon,
	plog,
	plogotlp,
	pmetric,
	pmetricotlp,
	ptrace,
	ptraceotlp,
	pprofile,
	pprofileotlp,
	xpdataEntity,
}

// Package is a struct used to generate files.
type Package struct {
	info *PackageInfo
	// Can be any of sliceOfPtrs, sliceOfValues, messageStruct.
	structs []baseStruct
}

type PackageInfo struct {
	name        string
	path        string
	imports     []string
	testImports []string
}

// GenerateFiles generates files with the configured data structures for this Package.
func (p *Package) GenerateFiles() error {
	for _, s := range p.structs {
		path := filepath.Join("pdata", p.info.path, "generated_"+strings.ToLower(s.getName())+".go")
		if err := os.WriteFile(path, s.generate(p.info), 0o600); err != nil {
			return err
		}
	}
	return nil
}

// GenerateTestFiles generates files with tests for the configured data structures for this Package.
func (p *Package) GenerateTestFiles() error {
	for _, s := range p.structs {
		path := filepath.Join("pdata", p.info.path, "generated_"+strings.ToLower(s.getName())+"_test.go")
		if err := os.WriteFile(path, s.generateTests(p.info), 0o600); err != nil {
			return err
		}
	}
	return nil
}

// GenerateInternalFiles generates files with internal pdata structures for this Package.
func (p *Package) GenerateInternalFiles() error {
	if !usedByOtherDataTypes(p.info.name) {
		return nil
	}

	for _, s := range p.structs {
		path := filepath.Join("pdata", "internal", "generated_wrapper_"+strings.ToLower(s.getName())+".go")
		if err := os.WriteFile(path, s.generateInternal(p.info), 0o600); err != nil {
			return err
		}
	}
	return nil
}

// usedByOtherDataTypes defines if the package is used by other data types and orig fields of the package's structs
// need to be accessible from other pdata packages.
func usedByOtherDataTypes(packageName string) bool {
	return packageName == "pcommon" || packageName == "entity"
}
