// Copyright (C) 2015 The Android Open Source Project
//
// 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.

package main

import (
	"flag"
	"fmt"
	"net"
	"os"
	"strings"
	"time"

	"android.googlesource.com/platform/tools/gpu/cc"
	. "android.googlesource.com/platform/tools/gpu/maker"
)

var targetOS = flag.String("targetos", HostOS, "target OS to build")

func main() { Run() }

const (
	GPURoot = "android.googlesource.com/platform/tools/gpu"
	// Request to send to replayd to have it shutdown. Note we do not use the
	// value in replay/protocol/connection_type.go to avoid introducing a
	// dependency on the code we are trying to build.
	ReplaydShutdownRequest = 2
)

var (
	gapirpath    = Path(gpusrc, "cc/gapir")
	gapiipath    = Path(gpusrc, "cc/gapii")
	gapiiwinpath = Path(gpusrc, "cc/gapii/windows")
	gapiiosxpath = Path(gpusrc, "cc/gapii/osx")
	cppcoder     = Path(gpusrc, "cc/gapic/coder")
	javabase     = Path(Paths.Root, "../")
	javapaths    = []string{
		Path(javabase, "base/rpclib/src/main/java/com/android/tools/rpclib"),
		Path(javabase, "base/rpclib/src/test/java/com/android/tools/rpclib"),
		Path(javabase, "adt/idea/android/src/com/android/tools/idea/editors/gfxtrace"),
	}
	gpusrc = GoSrcPath(GPURoot)

	Tools struct {
		Embed    Entity
		Apic     Entity
		Codergen Entity
		Gapit    Entity
	}

	Apps struct {
		Gapis Entity
		Gapir Entity
		Gapid Entity
	}
)

func init() {
	Register(func() {
		// Install rules for the build tools
		Tools.Embed = GoInstall(GPURoot + "/tools/embed")
		Tools.Apic = GoInstall(GPURoot + "/api/apic")
		Tools.Codergen = GoInstall(GPURoot + "/tools/codergen")
		Tools.Gapit = GoInstall(GPURoot + "/tools/gapit")
		List("gapit").DependsOn(Tools.Gapit)
		List("tools").DependsStruct(Tools)
		// All the embed rules
		embedCopyright := Embed(Path(gpusrc, "tools/copyright"))
		embedCodergen := Embed(Path(gpusrc, "tools/codergen/template"))
		Creator(Tools.Apic).DependsOn(embedCopyright)
		Creator(Tools.Codergen).DependsOn(embedCopyright, embedCodergen)
		// All the apic rules
		GfxApi("test", "gfxapi_test.api")
		GfxApi("gles", "gles.api")
		// The codergen rule
		Codergen("codergen", "--go", "--java", javabase, "-cpp", cppcoder, GPURoot+"/...")
		//
		List("code").DependsOn("embed", "apic", "codergen")
		// The native code rules
		cctargets := []string{*targetOS}
		if os.Getenv("ANDROID_NDK_ROOT") != "" {
			cctargets = append(cctargets, []string{"android-arm", "android-arm64"}...)
		}
		cc.Graph(cctargets)
		Apps.Gapir = Virtual("cc:replayd")
		Creator(Apps.Gapir).DependsOn(ShutdownReplayd(), "code")
		Creator("cc:spy").DependsOn("code")
		// The testing rules
		gotest := GoTest(GPURoot + "/...")
		// Runtime dependencies
		Creator(Tools.Gapit).DependsOn("cc:spy")
		List("runtime").DependsOn(Apps.Gapir, "cc:spy")
		Creator(gotest).DependsOn("code", "runtime")
		if *targetOS == HostOS {
			List("test").DependsOn("go_test", "cc_test")
		} else {
			List("test").DependsOn("go_test")
		}
		// The main binary rules
		Apps.Gapis = GoInstall(GPURoot + "/server/gapis")
		Creator(Apps.Gapis).DependsOn("code")
		Apps.Gapid = GoInstall(GPURoot + "/_experimental/client/gapid")
		Creator(Apps.Gapid).DependsOn("code")
		List("apps").DependsStruct(Apps)
		// Application launchers
		Command(Apps.Gapis).Creates(Virtual("gapis")).DependsOn(Apps.Gapir)
		Command(Apps.Gapid, "--gxuidebug").Creates(Virtual("gapid")).DependsOn(Apps.Gapis, "runtime")
		// Utilties
		GoRun(Path(gpusrc, "tools/clean_generated/main.go"), gpusrc).Creates(Virtual("clean_gpu"))
		GoRun(Path(gpusrc, "tools/clean_generated/main.go"), javapaths...).Creates(Virtual("clean_java"))
		GoRun(Path(gpusrc, "tools/copyright/copyright/main.go"), "-o", gpusrc).Creates(Virtual("copyright")).DependsOn(embedCopyright)
		// The default rules
		List(Default).DependsOn("apps", "test")
	})
}

func Embed(path string) Entity {
	out := File(path, "embed.go")
	args := []string{"--out", out.Name()}
	files := FilesOf(path, func(i os.FileInfo) bool {
		return !i.IsDir() && !strings.HasSuffix(i.Name(), ".go") && !strings.HasSuffix(i.Name(), ".md")
	})
	for _, f := range files {
		args = append(args, f.Name())
	}
	s := Command(Tools.Embed, args...).Creates(out)
	for _, f := range files {
		s.DependsOn(f)
	}
	List("embed").DependsOn(out)
	return out
}

func Apic(path string, api string, template string) {
	dst := Dir(path)
	a := File(api)
	t := File(template)
	_, apiname := PathSplit(api)
	_, templatename := PathSplit(template)
	deps := File(Paths.Deps, fmt.Sprintf("%v_%v.deps", apiname, templatename))
	s := Command(Tools.Apic,
		"template",
		"--dir", dst.Name(),
		"--deps", deps.Name(),
		a.Name(), t.Name()).DependsOn(a, t, dst, Dir(Paths.Deps))
	s.UseDepsFile(deps)
	List("apic").DependsOn(deps)
}

func Codergen(name string, args ...string) {
	Command(Tools.Codergen, args...).Creates(Virtual(name)).DependsOn("apic").Access(GoPkgResources)
}

func ShutdownReplayd() Entity {
	e := Virtual("shutdownreplayd")
	NewStep(func(*Step) error {
		for _, endpoint := range []string{"localhost:9283", "localhost:9284"} {
			const maxRetries = 10
			for i := 0; i < maxRetries; i++ {
				conn, err := net.Dial("tcp", endpoint)
				if err != nil {
					// Assume this means there is no replayd
					break
				}
				defer conn.Close()
				msg := []byte{ReplaydShutdownRequest}
				n, err := conn.Write(msg)
				if err != nil {
					return fmt.Errorf("Failed to send shutdown request to Replayd %v", err)
				}
				if n != len(msg) {
					return fmt.Errorf("Failed to send shutdown request to Replayd (only sent %v bytes", n)
				}
				if i == maxRetries-1 {
					return fmt.Errorf("Replayd at %v did not die", endpoint)
				}
				time.Sleep(100 * time.Millisecond)
			}
		}
		return nil
	}).Creates(e)
	return e
}

func GfxApi(pkg string, api string) {
	out := Path(gpusrc, "gfxapi", pkg)
	in := Path(out, api)
	templates := Path(gpusrc, "gfxapi", "templates")
	istest := strings.HasSuffix(pkg, "test")
	// go code
	Apic(out, in, Path(templates, "api.go.tmpl"))
	Apic(out, in, Path(templates, "replay_writer.go.tmpl"))
	Apic(out, in, Path(templates, "schema.go.tmpl"))
	Apic(out, in, Path(templates, "state_mutator.go.tmpl"))
	if istest {
		return
	}
	// gapir code
	Apic(gapirpath, in, Path(templates, "gfx_api.cpp.tmpl"))
	Apic(gapirpath, in, Path(templates, "gfx_api.h.tmpl"))
	// gapii code
	Apic(gapiipath, in, Path(templates, "api_exports.cpp.tmpl"))
	Apic(gapiipath, in, Path(templates, "api_imports.cpp.tmpl"))
	Apic(gapiipath, in, Path(templates, "api_imports.h.tmpl"))
	Apic(gapiipath, in, Path(templates, "api_spy.h.tmpl"))
	Apic(gapiipath, in, Path(templates, "api_types.h.tmpl"))
	Apic(gapiiwinpath, in, Path(templates, "opengl32_exports.def.tmpl"))
	Apic(gapiiwinpath, in, Path(templates, "opengl32_resolve.cpp.tmpl"))
	Apic(gapiiwinpath, in, Path(templates, "opengl32_x64.asm.tmpl"))
	Apic(gapiiosxpath, in, Path(templates, "opengl_framework_exports.cpp.tmpl"))
}
