// 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",
		},
	},
}

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
}
