// Copyright (C) 2016 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 android

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"

	"android.googlesource.com/platform/tools/gpu/framework/device"
	"android.googlesource.com/platform/tools/gpu/framework/log"
)

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

// InstalledPackage describes a package installed on a device.
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        device.ABI // The ABI of the package or empty
	Debuggable bool       // Whether the package is debuggable or not
}

// InstalledPackages is a list of installed packages.
type InstalledPackages []*InstalledPackage

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

// ErrProcessNotFound is returned by InstalledPackage.Pid when no running process of the package is found.
var ErrProcessNotFound = fmt.Errorf("Process not found")

// FindByName returns a list of installed packages who's name contains or equals
// s (case insensitive).
func (l InstalledPackages) FindByName(s string) InstalledPackages {
	s = strings.ToLower(s)
	found := make(InstalledPackages, 0, 1)
	for _, p := range l {
		if strings.Contains(strings.ToLower(p.Name), s) {
			found = append(found, p)
		}
	}
	return found
}

// FindSingleByName returns the single installed package who's name contains or
// equals s (case insensitive). If none or more than one packages partially
// matches s then an error is returned. If a package exactly matches s then that
// is returned regardless of any partial matches.
func (l InstalledPackages) FindSingleByName(s string) (*InstalledPackage, error) {
	found := l.FindByName(s)
	if len(found) == 0 {
		return nil, fmt.Errorf("No packages found containing the name '%v'", s)
	}

	if len(found) > 1 {
		names := make([]string, len(found))
		for i, p := range found {
			if p.Name == s { // Exact match
				return p, nil
			}
			names[i] = p.Name
		}
		return nil, fmt.Errorf("%v packages found containing the name '%v':\n%v",
			len(found), s, strings.Join(names, "\n"))
	}

	return found[0], nil
}

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

// SetWrapProperties sets the list of wrap-properties for the given installed
// package.
func (p *InstalledPackage) SetWrapProperties(ctx log.Context, props ...string) error {
	arg := strings.Join(props, " ")
	res, err := p.Device.Shell("setprop", p.wrapPropName(), arg).Call(ctx)
	if res != "" {
		return fmt.Errorf("setprop returned error:\n%s", res)
	}
	return err
}

// ClearCache deletes all data associated with a package.
func (p *InstalledPackage) ClearCache(ctx log.Context) error {
	return p.Device.Shell("pm", "clear", p.Name).Run(ctx)
}

// Stop stops any activities belonging to the package from running on the device.
func (p *InstalledPackage) Stop(ctx log.Context) error {
	return p.Device.Shell("am", "force-stop", p.Name).Run(ctx)
}

// Path returns the absolute path of the installed package on the device.
func (p *InstalledPackage) Path(ctx log.Context) (string, error) {
	out, err := p.Device.Shell("pm", "path", p.Name).Call(ctx)
	if err != nil {
		return "", err
	}
	prefix := "package:"
	if !strings.HasPrefix(out, prefix) {
		return "", fmt.Errorf("Unexpected output: '%s'", out)
	}
	path := out[len(prefix):]
	return path, err
}

// FileDir returns the absolute path of the installed packages files directory.
func (p *InstalledPackage) FileDir(ctx log.Context) (string, error) {
	out, err := p.Device.Shell("run-as", p.Name, "pwd").Call(ctx)
	if err != nil {
		return "", err
	}
	path := out + "/files"
	return path, err
}

// Pid returns the PID of the oldest (if pgrep exists) running process belonging to the given package.
func (p *InstalledPackage) Pid(ctx log.Context) (int, error) {
	// First, try pgrep.
	out, err := p.Device.Shell("pgrep", "-o", "-f", p.Name).Call(ctx)
	if err == nil {
		if out == "" {
			// Empty pgrep output. Process not found.
			return -1, ErrProcessNotFound
		}
		if regexp.MustCompile("^[0-9]+$").MatchString(out) {
			pid, _ := strconv.Atoi(out)
			return pid, nil
		}
	}

	// pgrep not found or other error, fall back to trying ps.
	out, err = p.Device.Shell("ps").Call(ctx)
	if err != nil {
		return -1, err
	}

	matches := regexp.MustCompile(
		`(?m)^\S+\s+([0-9]+)\s+[0-9]+\s+[0-9]+\s+[^\n\r]*\s+(\S+)\s*$`).FindAllStringSubmatch(out, -1)
	if matches != nil {
		// If we're here, we're getting sensible output from ps.
		for _, match := range matches {
			if match[2] == p.Name {
				pid, _ := strconv.Atoi(match[1])
				return pid, nil
			}
		}
		// Process not found.
		return -1, ErrProcessNotFound
	}

	return -1, fmt.Errorf("failed to get pid for package (pgrep and ps both missing or misbehaving)")
}

// Pull pulls the installed package from the device to the specified local directory.
func (p *InstalledPackage) Pull(ctx log.Context, target string) error {
	path, err := p.Path(ctx)
	if err != nil {
		return err
	}
	return p.Device.Pull(ctx, path, target)
}

// Uninstall uninstalls the package from the device.
func (p *InstalledPackage) Uninstall(ctx log.Context) error {
	return p.Device.Shell("pm", "uninstall", p.Name).Run(ctx)
}

// 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 {
		// The property name must not end in dot
		name = strings.TrimRight(name[:maxPropName], ".")
	}
	return name
}
