package bp2build

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

	"android/soong/android"
	"android/soong/shared"
	"android/soong/ui/metrics/bp2build_metrics_proto"

	"google.golang.org/protobuf/proto"

	"github.com/google/blueprint"
)

type moduleInfo struct {
	Name string `json:"name"`
	Type string `json:"type"`
}

// CodegenMetrics represents information about the Blueprint-to-BUILD
// conversion process.
// Use CreateCodegenMetrics() to get a properly initialized instance
type CodegenMetrics struct {
	serialized *bp2build_metrics_proto.Bp2BuildMetrics
	// List of modules with unconverted deps
	// NOTE: NOT in the .proto
	moduleWithUnconvertedDepsMsgs []string

	// List of modules with missing deps
	// NOTE: NOT in the .proto
	moduleWithMissingDepsMsgs []string

	// Map of converted modules and paths to call
	// NOTE: NOT in the .proto
	convertedModulePathMap map[string]string

	// Name and type of converted modules
	convertedModuleWithType []moduleInfo
}

func CreateCodegenMetrics() CodegenMetrics {
	return CodegenMetrics{
		serialized: &bp2build_metrics_proto.Bp2BuildMetrics{
			RuleClassCount:           make(map[string]uint64),
			ConvertedModuleTypeCount: make(map[string]uint64),
			TotalModuleTypeCount:     make(map[string]uint64),
			UnconvertedModules:       make(map[string]*bp2build_metrics_proto.UnconvertedReason),
		},
		convertedModulePathMap: make(map[string]string),
	}
}

// Serialize returns the protoized version of CodegenMetrics: bp2build_metrics_proto.Bp2BuildMetrics
func (metrics *CodegenMetrics) Serialize() *bp2build_metrics_proto.Bp2BuildMetrics {
	return metrics.serialized
}

// Print the codegen metrics to stdout.
func (metrics *CodegenMetrics) Print() {
	generatedTargetCount := uint64(0)
	for _, ruleClass := range android.SortedKeys(metrics.serialized.RuleClassCount) {
		count := metrics.serialized.RuleClassCount[ruleClass]
		fmt.Printf("[bp2build] %s: %d targets\n", ruleClass, count)
		generatedTargetCount += count
	}
	fmt.Printf(
		`[bp2build] Converted %d Android.bp modules to %d total generated BUILD targets. Included %d handcrafted BUILD targets. There are %d total Android.bp modules.
%d converted modules have unconverted deps:
	%s
%d converted modules have missing deps:
	%s
`,
		metrics.serialized.GeneratedModuleCount,
		generatedTargetCount,
		metrics.serialized.HandCraftedModuleCount,
		metrics.TotalModuleCount(),
		len(metrics.moduleWithUnconvertedDepsMsgs),
		strings.Join(metrics.moduleWithUnconvertedDepsMsgs, "\n\t"),
		len(metrics.moduleWithMissingDepsMsgs),
		strings.Join(metrics.moduleWithMissingDepsMsgs, "\n\t"),
	)
}

const bp2buildMetricsFilename = "bp2build_metrics.pb"

// fail prints $PWD to stderr, followed by the given printf string and args (vals),
// then the given alert, and then exits with 1 for failure
func fail(err error, alertFmt string, vals ...interface{}) {
	cwd, wderr := os.Getwd()
	if wderr != nil {
		cwd = "FAILED TO GET $PWD: " + wderr.Error()
	}
	fmt.Fprintf(os.Stderr, "\nIn "+cwd+":\n"+alertFmt+"\n"+err.Error()+"\n", vals...)
	os.Exit(1)
}

// Write the bp2build-protoized codegen metrics into the given directory
func (metrics *CodegenMetrics) Write(dir string) {
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		// The metrics dir doesn't already exist, so create it (and parents)
		if err := os.MkdirAll(dir, 0755); err != nil { // rx for all; w for user
			fail(err, "Failed to `mkdir -p` %s", dir)
		}
	} else if err != nil {
		fail(err, "Failed to `stat` %s", dir)
	}
	metricsFile := filepath.Join(dir, bp2buildMetricsFilename)
	if err := metrics.dump(metricsFile); err != nil {
		fail(err, "Error outputting %s", metricsFile)
	}
	if _, err := os.Stat(metricsFile); err != nil {
		if os.IsNotExist(err) {
			fail(err, "MISSING BP2BUILD METRICS OUTPUT: %s", metricsFile)
		} else {
			fail(err, "FAILED TO `stat` BP2BUILD METRICS OUTPUT: %s", metricsFile)
		}
	}
}

// ReadCodegenMetrics loads CodegenMetrics from `dir`
// returns a nil pointer if the file doesn't exist
func ReadCodegenMetrics(dir string) *CodegenMetrics {
	metricsFile := filepath.Join(dir, bp2buildMetricsFilename)
	if _, err := os.Stat(metricsFile); err != nil {
		if os.IsNotExist(err) {
			return nil
		} else {
			fail(err, "FAILED TO `stat` BP2BUILD METRICS OUTPUT: %s", metricsFile)
			panic("unreachable after fail")
		}
	}
	if buf, err := os.ReadFile(metricsFile); err != nil {
		fail(err, "FAILED TO READ BP2BUILD METRICS OUTPUT: %s", metricsFile)
		panic("unreachable after fail")
	} else {
		bp2BuildMetrics := bp2build_metrics_proto.Bp2BuildMetrics{
			RuleClassCount:           make(map[string]uint64),
			ConvertedModuleTypeCount: make(map[string]uint64),
			TotalModuleTypeCount:     make(map[string]uint64),
		}
		if err := proto.Unmarshal(buf, &bp2BuildMetrics); err != nil {
			fail(err, "FAILED TO PARSE BP2BUILD METRICS OUTPUT: %s", metricsFile)
		}
		return &CodegenMetrics{
			serialized:             &bp2BuildMetrics,
			convertedModulePathMap: make(map[string]string),
		}
	}
}

func (metrics *CodegenMetrics) IncrementRuleClassCount(ruleClass string) {
	metrics.serialized.RuleClassCount[ruleClass] += 1
}

func (metrics *CodegenMetrics) AddEvent(event *bp2build_metrics_proto.Event) {
	metrics.serialized.Events = append(metrics.serialized.Events, event)
}

func (metrics *CodegenMetrics) SetSymlinkCount(n uint64) {
	if m := metrics.serialized.WorkspaceSymlinkCount; m != 0 {
		fmt.Fprintf(os.Stderr, "unexpected non-zero workspaceSymlinkCount of %d", m)
	}
	metrics.serialized.WorkspaceSymlinkCount = n
}

func (metrics *CodegenMetrics) SetMkDirCount(n uint64) {
	if m := metrics.serialized.WorkspaceMkDirCount; m != 0 {
		fmt.Fprintf(os.Stderr, "unexpected non-zero workspaceDirCount of %d", m)
	}
	metrics.serialized.WorkspaceMkDirCount = n
}

func (metrics *CodegenMetrics) TotalModuleCount() uint64 {
	return metrics.serialized.HandCraftedModuleCount +
		metrics.serialized.GeneratedModuleCount +
		metrics.serialized.UnconvertedModuleCount
}

// Dump serializes the metrics to the given filename
func (metrics *CodegenMetrics) dump(filename string) (err error) {
	ser := metrics.Serialize()
	return shared.Save(ser, filename)
}

type ConversionType int

const (
	Generated ConversionType = iota
	Handcrafted
)

func (metrics *CodegenMetrics) AddConvertedModule(m blueprint.Module, moduleType string, dir string) {
	//a package module has empty name
	if moduleType == "package" {
		return
	}
	// Undo prebuilt_ module name prefix modifications
	moduleName := android.RemoveOptionalPrebuiltPrefix(m.Name())
	metrics.serialized.ConvertedModules = append(metrics.serialized.ConvertedModules, moduleName)
	metrics.convertedModuleWithType = append(metrics.convertedModuleWithType, moduleInfo{
		moduleName,
		moduleType,
	})
	metrics.convertedModulePathMap[moduleName] = "//" + dir
	metrics.serialized.ConvertedModuleTypeCount[moduleType] += 1
	metrics.serialized.TotalModuleTypeCount[moduleType] += 1
	metrics.serialized.GeneratedModuleCount += 1
}

func (metrics *CodegenMetrics) AddUnconvertedModule(m blueprint.Module, moduleType string, dir string,
	reason android.UnconvertedReason) {
	//a package module has empty name
	if moduleType == "package" {
		return
	}
	// Undo prebuilt_ module name prefix modifications
	moduleName := android.RemoveOptionalPrebuiltPrefix(m.Name())
	metrics.serialized.UnconvertedModules[moduleName] = &bp2build_metrics_proto.UnconvertedReason{
		Type:   bp2build_metrics_proto.UnconvertedReasonType(reason.ReasonType),
		Detail: reason.Detail,
	}
	metrics.serialized.UnconvertedModuleCount += 1
	metrics.serialized.TotalModuleTypeCount[moduleType] += 1

	if reason.ReasonType == int(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE) {
		metrics.serialized.HandCraftedModuleCount += 1
	}
}
