// 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
)

var buildBrokenSettings = []struct {
	name     string
	behavior BuildBrokenBehavior
	warnings []string
}{
	{
		name:     "BUILD_BROKEN_DUP_COPY_HEADERS",
		behavior: DefaultDeprecated,
		warnings: []string{"Duplicate header copy:"},
	},
	{
		name:     "BUILD_BROKEN_DUP_RULES",
		behavior: DefaultFalse,
		warnings: []string{"overriding commands for target"},
	},
	{
		name:     "BUILD_BROKEN_ANDROIDMK_EXPORTS",
		behavior: DefaultFalse,
		warnings: []string{"export_keyword"},
	},
	{
		name:     "BUILD_BROKEN_PHONY_TARGETS",
		behavior: DefaultFalse,
		warnings: []string{
			"depends on PHONY target",
			"looks like a real file",
			"writing to readonly directory",
		},
	},
	{
		name:     "BUILD_BROKEN_ENG_DEBUG_TAGS",
		behavior: DefaultTrue,
		warnings: []string{
			"Changes.md#LOCAL_MODULE_TAGS",
		},
	},
	{
		name:     "BUILD_BROKEN_USES_NETWORK",
		behavior: DefaultDeprecated,
	},
}

type ProductBranch struct {
	Branch string
	Name   string
}

type ProductLog struct {
	ProductBranch
	Log
	Device string
}

type Log struct {
	BuildBroken []*bool
	HasBroken   []bool
}

func Merge(l, l2 Log) Log {
	if len(l.BuildBroken) == 0 {
		l.BuildBroken = make([]*bool, len(buildBrokenSettings))
	}
	if len(l.HasBroken) == 0 {
		l.HasBroken = make([]bool, len(buildBrokenSettings))
	}

	if len(l.BuildBroken) != len(l2.BuildBroken) || len(l.HasBroken) != len(l2.HasBroken) {
		panic("mis-matched logs")
	}

	for i, v := range l.BuildBroken {
		if v == nil {
			l.BuildBroken[i] = l2.BuildBroken[i]
		}
	}
	for i := range l.HasBroken {
		l.HasBroken[i] = l.HasBroken[i] || l2.HasBroken[i]
	}

	return l
}

func PrintResults(products []ProductLog) {
	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 i, setting := range buildBrokenSettings {
		printed := false

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

			if setting.behavior == DefaultTrue {
				if log.BuildBroken[i] == nil || *log.BuildBroken[i] == false {
					if log.HasBroken[i] {
						printed = true
						fmt.Printf("  %s needs to set %s := true\n", device, setting.name)
					}
				} else if !log.HasBroken[i] {
					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[i] == nil {
					// Nothing to be done
				} else if *log.BuildBroken[i] == 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[i] {
					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[i] != nil {
					printed = true
					if log.HasBroken[i] {
						fmt.Printf("  %s sets %s := %v, which is deprecated, but has failures\n", device, setting.name, *log.BuildBroken[i])
					} else {
						fmt.Printf("  %s sets %s := %v, which is deprecated and can be removed\n", device, setting.name, *log.BuildBroken[i])
					}
				}
			}
		}

		if printed {
			fmt.Println()
		}
	}
}

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

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

		ret = append(ret, ParseProduct(ProductBranch{Branch: name, Name: product}))
	}
	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: make([]*bool, len(buildBrokenSettings)),
			HasBroken:   make([]bool, len(buildBrokenSettings)),
		},
	}

	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 strings.HasPrefix(fields[3], "BUILD_BROKEN_") {
			for i, setting := range buildBrokenSettings {
				if setting.name == fields[3] {
					ret.BuildBroken[i] = ParseBoolPtr(fields[4])
				}
			}
		}
	}

	stdLog, err := ioutil.ReadFile(filepath.Join(p.Branch, p.Name, "std_full.log"))
	if err != nil {
		log.Fatal(err)
	}
	stdStr := string(stdLog)

	for i, setting := range buildBrokenSettings {
		for _, warning := range setting.warnings {
			if strings.Contains(stdStr, warning) {
				ret.HasBroken[i] = true
			}
		}
	}

	return ret
}

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