// Copyright 2019 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// This is a script that can be used to analyze the results from
// build/soong/build_test.bash and recommend what devices need changes to their
// BUILD_BROKEN_* flags.
//
// To use, download the logs.zip from one or more branches, and extract them
// into subdirectories of the current directory. So for example, I have:
//
//	./aosp-master/aosp_arm/std_full.log
//	./aosp-master/aosp_arm64/std_full.log
//	./aosp-master/...
//	./internal-master/aosp_arm/std_full.log
//	./internal-master/aosp_arm64/std_full.log
//	./internal-master/...
//
// Then I use `go run path/to/build_broken_logs.go *`
package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"sort"
	"strings"
)

func main() {
	for _, branch := range os.Args[1:] {
		fmt.Printf("\nBranch %s:\n", branch)
		PrintResults(ParseBranch(branch))
	}
}

type BuildBrokenBehavior int

const (
	DefaultFalse BuildBrokenBehavior = iota
	DefaultTrue
	DefaultDeprecated
)

type Setting struct {
	name     string
	behavior BuildBrokenBehavior
	warnings []string
}

var buildBrokenSettings = []Setting{
	{
		name:     "BUILD_BROKEN_DUP_RULES",
		behavior: DefaultFalse,
		warnings: []string{"overriding commands for target"},
	},
	{
		name:     "BUILD_BROKEN_USES_NETWORK",
		behavior: DefaultDeprecated,
	},
	{
		name:     "BUILD_BROKEN_USES_BUILD_COPY_HEADERS",
		behavior: DefaultTrue,
		warnings: []string{
			"COPY_HEADERS has been deprecated",
			"COPY_HEADERS is deprecated",
		},
	},
}

type Branch struct {
	Settings []Setting
	Logs     []ProductLog
}

type ProductBranch struct {
	Branch string
	Name   string
}

type ProductLog struct {
	ProductBranch
	Log
	Device string
}

type Log struct {
	WarningModuleTypes []string
	ErrorModuleTypes   []string

	BuildBroken map[string]*bool
	HasBroken   map[string]int
}

func Merge(l, l2 Log) Log {
	if l.BuildBroken == nil {
		l.BuildBroken = map[string]*bool{}
	}
	if l.HasBroken == nil {
		l.HasBroken = map[string]int{}
	}

	for n, v := range l.BuildBroken {
		if v == nil {
			l.BuildBroken[n] = l2.BuildBroken[n]
		}
	}
	for n, v := range l2.BuildBroken {
		if _, ok := l.BuildBroken[n]; !ok {
			l.BuildBroken[n] = v
		}
	}

	for n := range l.HasBroken {
		if l.HasBroken[n] < l2.HasBroken[n] {
			l.HasBroken[n] = l2.HasBroken[n]
		}
	}
	for n := range l2.HasBroken {
		if _, ok := l.HasBroken[n]; !ok {
			l.HasBroken[n] = l2.HasBroken[n]
		}
	}

	return l
}

func PrintResults(branch Branch) {
	products := branch.Logs
	devices := map[string]Log{}
	deviceNames := []string{}

	for _, product := range products {
		device := product.Device
		if _, ok := devices[device]; !ok {
			deviceNames = append(deviceNames, device)
		}
		devices[device] = Merge(devices[device], product.Log)
	}

	sort.Strings(deviceNames)

	for _, setting := range branch.Settings {
		printed := false
		n := setting.name

		for _, device := range deviceNames {
			log := devices[device]

			if setting.behavior == DefaultTrue {
				if log.BuildBroken[n] == nil || *log.BuildBroken[n] == false {
					if log.HasBroken[n] > 0 {
						printed = true
						plural := ""
						if log.HasBroken[n] > 1 {
							plural = "s"
						}
						fmt.Printf("  %s needs to set %s := true  (%d instance%s)\n", device, setting.name, log.HasBroken[n], plural)
					}
				} else if log.HasBroken[n] == 0 {
					printed = true
					fmt.Printf("  %s sets %s := true, but does not need it\n", device, setting.name)
				}
			} else if setting.behavior == DefaultFalse {
				if log.BuildBroken[n] == nil {
					// Nothing to be done
				} else if *log.BuildBroken[n] == false {
					printed = true
					fmt.Printf("  %s sets %s := false, which is the default and can be removed\n", device, setting.name)
				} else if log.HasBroken[n] == 0 {
					printed = true
					fmt.Printf("  %s sets %s := true, but does not need it\n", device, setting.name)
				}
			} else if setting.behavior == DefaultDeprecated {
				if log.BuildBroken[n] != nil {
					printed = true
					if log.HasBroken[n] > 0 {
						plural := ""
						if log.HasBroken[n] > 1 {
							plural = "s"
						}
						fmt.Printf("  %s sets %s := %v, which is deprecated, but has %d failure%s\n", device, setting.name, *log.BuildBroken[n], log.HasBroken[n], plural)
					} else {
						fmt.Printf("  %s sets %s := %v, which is deprecated and can be removed\n", device, setting.name, *log.BuildBroken[n])
					}
				}
			}
		}

		if printed {
			fmt.Println()
		}
	}
}

func ParseBranch(name string) Branch {
	products, err := filepath.Glob(filepath.Join(name, "*"))
	if err != nil {
		log.Fatal(err)
	}

	ret := Branch{Logs: []ProductLog{}}
	for _, product := range products {
		product = filepath.Base(product)

		ret.Logs = append(ret.Logs, ParseProduct(ProductBranch{Branch: name, Name: product}))
	}

	ret.Settings = append(ret.Settings, buildBrokenSettings...)
	if len(ret.Logs) > 0 {
		for _, mtype := range ret.Logs[0].WarningModuleTypes {
			if mtype == "BUILD_COPY_HEADERS" || mtype == "" {
				continue
			}
			ret.Settings = append(ret.Settings, Setting{
				name:     "BUILD_BROKEN_USES_" + mtype,
				behavior: DefaultTrue,
				warnings: []string{mtype + " has been deprecated"},
			})
		}
		for _, mtype := range ret.Logs[0].ErrorModuleTypes {
			if mtype == "BUILD_COPY_HEADERS" || mtype == "" {
				continue
			}
			ret.Settings = append(ret.Settings, Setting{
				name:     "BUILD_BROKEN_USES_" + mtype,
				behavior: DefaultFalse,
				warnings: []string{mtype + " has been deprecated"},
			})
		}
	}

	for _, productLog := range ret.Logs {
		ScanProduct(ret.Settings, productLog)
	}
	return ret
}

func ParseProduct(p ProductBranch) ProductLog {
	soongLog, err := ioutil.ReadFile(filepath.Join(p.Branch, p.Name, "soong.log"))
	if err != nil {
		log.Fatal(err)
	}

	ret := ProductLog{
		ProductBranch: p,
		Log: Log{
			BuildBroken: map[string]*bool{},
			HasBroken:   map[string]int{},
		},
	}

	lines := strings.Split(string(soongLog), "\n")
	for _, line := range lines {
		fields := strings.Split(line, " ")
		if len(fields) < 5 {
			continue
		}

		if fields[3] == "TARGET_DEVICE" {
			ret.Device = fields[4]
		}

		if fields[3] == "DEFAULT_WARNING_BUILD_MODULE_TYPES" {
			ret.WarningModuleTypes = fields[4:]
		}
		if fields[3] == "DEFAULT_ERROR_BUILD_MODULE_TYPES" {
			ret.ErrorModuleTypes = fields[4:]
		}

		if strings.HasPrefix(fields[3], "BUILD_BROKEN_") {
			ret.BuildBroken[fields[3]] = ParseBoolPtr(fields[4])
		}
	}

	return ret
}

func ScanProduct(settings []Setting, l ProductLog) {
	stdLog, err := ioutil.ReadFile(filepath.Join(l.Branch, l.Name, "std_full.log"))
	if err != nil {
		log.Fatal(err)
	}
	stdStr := string(stdLog)

	for _, setting := range settings {
		for _, warning := range setting.warnings {
			if strings.Contains(stdStr, warning) {
				l.HasBroken[setting.name] += strings.Count(stdStr, warning)
			}
		}
	}
}

func ParseBoolPtr(str string) *bool {
	var ret *bool
	if str != "" {
		b := str == "true"
		ret = &b
	}
	return ret
}
