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

import (
	"fmt"
	"sort"
	"strings"
)

// https://android.googlesource.com/platform/bionic/+/master/libc/include/sys/system_properties.h#38
// Actually 32, but that includes null-terminator.
const maxPropName = 31

type InstalledPackage struct {
	Name    string    // Name of the package.
	Device  *Device   // The device this package is installed on.
	Actions []*Action // The actions this package supports.
	ABI     string    // The ABI of the package or empty
}

// WrapProperties returns the list of wrap-properties for the given installed
// package.
func (p *InstalledPackage) WrapProperties() ([]string, error) {
	list, err := p.Device.Command("getprop", p.wrapPropName()).Call()
	return strings.Fields(list), err
}

// WrapProperties sets the list of wrap-properties for the given installed
// package.
func (p *InstalledPackage) SetWrapProperties(props ...string) error {
	arg := strings.Join(props, " ")
	return p.Device.Command("setprop", p.wrapPropName(), arg).Run()
}

// Action represents an Android action that can be sent as an intent.
type Action struct {
	Name     string // Example: android.intent.action.MAIN
	Package  *InstalledPackage
	Activity string // Example: .FooBarActivity
}

// String returns the package name.
func (p *InstalledPackage) String() string {
	return p.Name
}

func (p *InstalledPackage) wrapPropName() string {
	name := "wrap." + p.Name
	if len(name) > maxPropName {
		name = name[:maxPropName]
	}
	return name
}

func (a *Action) String() string {
	return a.Name + ":" + a.Package.Name + "/" + a.Activity
}

// InstalledPackages returns the sorted list of installed packages on the device.
func (d *Device) InstalledPackages() (Packages, error) {
	str, err := d.Command("dumpsys", "package").Call()
	if err != nil {
		return nil, err
	}
	return d.parsePackages(str)
}

func (d *Device) parsePackages(str string) (Packages, error) {
	tree := parseTabbedTree(str)
	activities := tree.find("Activity Resolver Table:")
	if activities == nil {
		return nil, fmt.Errorf("Could not find Activity Resolver Table in dumpsys")
	}
	actions := activities.find("Non-Data Actions:")
	if actions == nil {
		return nil, fmt.Errorf("Could not find Non-Data Actions in dumpsys")
	}
	packageMap := map[string]*InstalledPackage{}
	for _, action := range actions.children {
		for _, entry := range action.children {
			// 43178558 com.google.foo/.FooActivity filter 431d7db8
			// 43178558 com.google.foo/.FooActivity
			fields := strings.Fields(entry.text)
			if len(fields) < 2 {
				return nil, fmt.Errorf("Could not parse package: '%v'", entry.text)
			}
			component := fields[1]
			parts := strings.SplitN(component, "/", 2)
			name := parts[0]
			p, ok := packageMap[name]
			if !ok {
				p = &InstalledPackage{
					Name:    name,
					Device:  d,
					Actions: []*Action{},
				}
				packageMap[name] = p
			}
			p.Actions = append(p.Actions, &Action{
				Package:  p,
				Name:     strings.TrimRight(action.text, ":"),
				Activity: parts[1],
			})
		}
	}
	// Read the "Packages:" section if it is present and use it to set ABI
	packSection := tree.find("Packages:")
	if packSection != nil {
		for _, pack := range packSection.children {
			// Package [com.google.foo] (ffffffc):
			fields := strings.Fields(pack.text)
			if len(fields) != 3 {
				continue
			}
			name := strings.Trim(fields[1], "[]")
			ip, ok := packageMap[name]
			if !ok {
				// We didn't find an action for this package
				continue
			}

			for _, attr := range pack.children {
				// primaryCpuAbi=arm64-v8a
				// primaryCpuAbi=null
				av := strings.TrimSpace(attr.text)
				if !strings.HasPrefix(av, "primaryCpuAbi=") {
					continue
				}
				splits := strings.SplitN(av, "=", 2)
				if len(splits) < 2 {
					break
				}
				if splits[1] == "null" {
					// This means the package manager will select the platform ABI
					break
				}
				ip.ABI = splits[1]
			}
		}
	}
	packages := make(Packages, 0, len(packageMap))
	for _, p := range packageMap {
		packages = append(packages, p)
	}
	sort.Sort(packages)
	return packages, nil
}

type Packages []*InstalledPackage

func (l Packages) Len() int           { return len(l) }
func (l Packages) Less(i, j int) bool { return l[i].Name < l[j].Name }
func (l Packages) Swap(i, j int)      { l[i], l[j] = l[j], l[i] }

type treeNode struct {
	text     string
	children []*treeNode
	parent   *treeNode
	depth    int
}

func (t *treeNode) find(name string) *treeNode {
	if t == nil {
		return nil
	}
	for _, c := range t.children {
		if c.text == name {
			return c
		}
	}
	return nil
}

func parseTabbedTree(str string) *treeNode {
	head := &treeNode{depth: -1}
	for _, line := range strings.Split(str, "\n") {
		line = strings.TrimRight(line, "\r")
		if line == "" {
			continue
		}

		// Calculate the line's depth
		depth := 0
		for i, r := range line {
			if r == ' ' {
				depth++
			} else {
				line = line[i:]
				break
			}
		}

		// Find the insertion point
		for {
			if head.depth >= depth {
				head = head.parent
			} else {
				node := &treeNode{text: line, depth: depth, parent: head}
				head.children = append(head.children, node)
				head = node
				break
			}
		}
	}
	for head.parent != nil {
		head = head.parent
	}
	return head
}
