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

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"os/user"
	"path/filepath"
	"time"

	"android.googlesource.com/platform/tools/gpu/adb"
	"android.googlesource.com/platform/tools/gpu/gapii"
	"android.googlesource.com/platform/tools/gpu/log"
	"github.com/google/gxui"
	"github.com/google/gxui/math"
)

var (
	spyport = flag.Int("i", 9286, "gapii TCP port to connect to")
)

type launchNode struct {
	text   string
	items  []*launchNode
	action *adb.Action
}

func (n *launchNode) String() string {
	return n.text
}

func (n *launchNode) Count() int {
	return len(n.items)
}

func (n *launchNode) NodeAt(index int) gxui.TreeNode {
	return n.items[index]
}

func (n *launchNode) ItemIndex(item gxui.AdapterItem) int {
	find, ok := item.(*launchNode)
	if !ok {
		return -1
	}
	for i, test := range n.items {
		if test == find || test.ItemIndex(item) >= 0 {
			return i
		}
	}
	return -1
}

func (n *launchNode) Item() gxui.AdapterItem {
	return n
}

func (n *launchNode) Create(theme gxui.Theme) gxui.Control {
	label := theme.CreateLabel()
	label.SetText(n.text)
	return label
}

type launchAdapter struct {
	gxui.AdapterBase
	launchNode
}

func (a *launchAdapter) Size(t gxui.Theme) math.Size {
	return math.Size{W: math.MaxSize.W, H: 18}
}

func CreateLaunchAndroidDialog(theme gxui.Theme, statusLogger log.Logger, capture func()) {
	driver := theme.Driver()
	window := theme.CreateWindow(500, 800, "Launch Android application...")

	overlay := theme.CreateBubbleOverlay()

	deviceAdapter := gxui.CreateDefaultAdapter()

	devices, _ := adb.Devices()
	deviceAdapter.SetItems(devices)

	deviceList := theme.CreateDropDownList()
	deviceList.SetAdapter(deviceAdapter)
	deviceList.SetBubbleOverlay(overlay)

	packageList := theme.CreateTree()

	deviceList.OnSelectionChanged(func(sel gxui.AdapterItem) {
		device := sel.(*adb.Device)
		go func() error {
			adapter := &launchAdapter{}
			err := device.Root()
			switch err {
			case nil:
			case adb.ErrDeviceNotRooted:
				return err
			default:
				return fmt.Errorf("Failed to restart ADB as root: %v", err)
			}
			packages, err := device.InstalledPackages()
			if len(packages) == 0 || err != nil {
				return fmt.Errorf(fmt.Sprintf("Could not get list of installed packages: %v", err))
			}
			for _, pkg := range packages {
				var pkgNode *launchNode
				for _, action := range pkg.Actions {
					if action.Name == "android.intent.action.MAIN" {
						if pkgNode == nil {
							pkgNode = &launchNode{
								text: pkg.Name,
							}
							adapter.items = append(adapter.items, pkgNode)
						}
						pkgNode.items = append(pkgNode.items, &launchNode{
							text:   action.Activity,
							action: action,
						})
					}
				}
			}
			driver.CallSync(func() {
				packageList.SetAdapter(adapter)
			})
			return nil
		}()
	})

	packageList.OnDoubleClick(func(gxui.MouseEvent) {
		if sel := packageList.Selected(); sel != nil {
			if item, ok := sel.(*launchNode); ok {
				if item.action != nil {
					go func() {
						driver.Call(window.Close)
						gapii.AdbStart(statusLogger, item.action, adb.TCPPort(*spyport), false)
						capture()
					}()
				}
			}
		}
	})

	layout := theme.CreateLinearLayout()
	layout.AddChild(deviceList)
	layout.AddChild(packageList)

	window.AddChild(layout)
	window.AddChild(overlay)

	if len(devices) > 0 {
		deviceList.Select(devices[0])
	}
}

func CreateTakeCaptureDialog(appCtx *ApplicationContext) {
	theme := appCtx.theme
	window := theme.CreateWindow(500, 200, "Take capture")

	launch := theme.CreateButton()
	launch.SetText("Launch...")

	button := theme.CreateButton()
	button.SetText("Capture...")

	load := theme.CreateButton()
	load.SetText("Import...")

	namelbl := theme.CreateLabel()
	namelbl.SetText("Capture name:")

	name := theme.CreateTextBox()
	name.SetDesiredWidth(math.MaxSize.W)
	name.SetText(time.Now().String())

	top := theme.CreateLinearLayout()
	top.SetSizeMode(gxui.Fill)
	top.SetDirection(gxui.TopToBottom)

	row := theme.CreateLinearLayout()
	row.SetDirection(gxui.LeftToRight)
	row.AddChild(namelbl)
	row.AddChild(name)
	top.AddChild(row)

	statusAdapter := CreateLogAdapter(1024, appCtx.Run)
	statusLogger := statusAdapter.Logger()
	status := theme.CreateList()
	status.SetAdapter(statusAdapter)
	top.AddChild(status)

	bottom := theme.CreateLinearLayout()
	bottom.SetDirection(gxui.RightToLeft)
	bottom.AddChild(button)
	bottom.AddChild(launch)
	bottom.AddChild(load)

	layout := theme.CreateLinearLayout()
	layout.SetDirection(gxui.BottomToTop)
	layout.AddChild(bottom)
	layout.AddChild(top)

	window.AddChild(layout)

	var clickSubscription gxui.EventSubscription
	capture := func() {
		stop := make(chan struct{})

		clickSubscription.Unlisten()
		theme.Driver().Call(func() {
			button.SetText("Stop")
		})
		clickSubscription = button.OnClick(func(gxui.MouseEvent) {
			clickSubscription.Unlisten()
			close(stop)
		})

		go func() {
			buf := &bytes.Buffer{}
			count, err := gapii.Capture(statusLogger, *spyport, buf, stop)
			if count > 0 {
				data := buf.Bytes()
				log.Infof(statusLogger, "Importing...")
				p, err := appCtx.rpc.Import(name.Text(), data)
				if err != nil {
					panic(err)
				}

				log.Infof(statusLogger, "Loading...")

				appCtx.Run(func() {
					appCtx.events.Select(p)
					window.Close()
				})
			} else {
				if err != nil {
					log.Errorf(statusLogger, "%T %s", err, err.Error())
				}
				appCtx.Run(func() {
					button.SetText("Close")
					button.OnClick(func(gxui.MouseEvent) {
						window.Close()
					})
				})
			}
		}()
	}

	clickSubscription = button.OnClick(func(gxui.MouseEvent) { capture() })
	launch.OnClick(func(ev gxui.MouseEvent) {
		CreateLaunchAndroidDialog(theme, statusLogger, capture)
	})

	load.OnClick(func(ev gxui.MouseEvent) {
		go func() {
			ImportCapture(appCtx, name.Text(), statusLogger)
			theme.Driver().Call(func() {
				window.Close()
			})
		}()
	})
}

func ImportCapture(appCtx *ApplicationContext, path string, statusLogger log.Logger) {
	if path[:2] == "~/" {
		usr, _ := user.Current()
		path = filepath.Join(usr.HomeDir, path[2:])
	}
	log.Infof(statusLogger, "Loading %s", path)
	data, err := ioutil.ReadFile(path)
	if err != nil {
		log.Infof(statusLogger, "Failed opening file %s: %s", path, err)
	} else if len(data) == 0 {
		log.Infof(statusLogger, "Zero size file %s", path)
	} else {
		log.Infof(statusLogger, "Importing...")
		p, err := appCtx.rpc.Import(path, data)
		if err != nil {
			panic(err)
		}
		log.Infof(statusLogger, "Loading...")
		appCtx.events.Select(p)
	}
}
