// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build ignore

// detect attempts to autodetect the correct
// values of the environment variables
// used by go_ios_exec.
// detect shells out to ideviceinfo, a third party program that can
// be obtained by following the instructions at
// https://github.com/libimobiledevice/libimobiledevice.
package main

import (
	"bytes"
	"crypto/x509"
	"fmt"
	"os"
	"os/exec"
	"strings"
)

func main() {
	udids := getLines(exec.Command("idevice_id", "-l"))
	if len(udids) == 0 {
		fail("no udid found; is a device connected?")
	}

	mps := detectMobileProvisionFiles(udids)
	if len(mps) == 0 {
		fail("did not find mobile provision matching device udids %q", udids)
	}

	fmt.Println("# Available provisioning profiles below.")
	fmt.Println("# NOTE: Any existing app on the device with the app id specified by GOIOS_APP_ID")
	fmt.Println("# will be overwritten when running Go programs.")
	for _, mp := range mps {
		fmt.Println()
		f, err := os.CreateTemp("", "go_ios_detect_")
		check(err)
		fname := f.Name()
		defer os.Remove(fname)

		out := output(parseMobileProvision(mp))
		_, err = f.Write(out)
		check(err)
		check(f.Close())

		cert, err := plistExtract(fname, "DeveloperCertificates:0")
		check(err)
		pcert, err := x509.ParseCertificate(cert)
		check(err)
		fmt.Printf("export GOIOS_DEV_ID=\"%s\"\n", pcert.Subject.CommonName)

		appID, err := plistExtract(fname, "Entitlements:application-identifier")
		check(err)
		fmt.Printf("export GOIOS_APP_ID=%s\n", appID)

		teamID, err := plistExtract(fname, "Entitlements:com.apple.developer.team-identifier")
		check(err)
		fmt.Printf("export GOIOS_TEAM_ID=%s\n", teamID)
	}
}

func detectMobileProvisionFiles(udids [][]byte) []string {
	cmd := exec.Command("mdfind", "-name", ".mobileprovision")
	lines := getLines(cmd)

	var files []string
	for _, line := range lines {
		if len(line) == 0 {
			continue
		}
		xmlLines := getLines(parseMobileProvision(string(line)))
		matches := 0
		for _, udid := range udids {
			for _, xmlLine := range xmlLines {
				if bytes.Contains(xmlLine, udid) {
					matches++
				}
			}
		}
		if matches == len(udids) {
			files = append(files, string(line))
		}
	}
	return files
}

func parseMobileProvision(fname string) *exec.Cmd {
	return exec.Command("security", "cms", "-D", "-i", string(fname))
}

func plistExtract(fname string, path string) ([]byte, error) {
	out, err := exec.Command("/usr/libexec/PlistBuddy", "-c", "Print "+path, fname).CombinedOutput()
	if err != nil {
		return nil, err
	}
	return bytes.TrimSpace(out), nil
}

func getLines(cmd *exec.Cmd) [][]byte {
	out := output(cmd)
	lines := bytes.Split(out, []byte("\n"))
	// Skip the empty line at the end.
	if len(lines[len(lines)-1]) == 0 {
		lines = lines[:len(lines)-1]
	}
	return lines
}

func output(cmd *exec.Cmd) []byte {
	out, err := cmd.Output()
	if err != nil {
		fmt.Println(strings.Join(cmd.Args, "\n"))
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	return out
}

func check(err error) {
	if err != nil {
		fail(err.Error())
	}
}

func fail(msg string, v ...interface{}) {
	fmt.Fprintf(os.Stderr, msg, v...)
	fmt.Fprintln(os.Stderr)
	os.Exit(1)
}
