package aapt

import (
	"archive/zip"
	"log"
	"strings"

	"notabug.org/Umnik/GoAndroidSDK/v2/components/misc"
)

func findApkSignature(apkFile string) ([]string, error) {
	zipReader, err := zip.OpenReader(apkFile)
	if err != nil {
		return nil, err
	}
	defer func(zipReader *zip.ReadCloser) {
		if e := zipReader.Close(); e != nil {
			log.Print(e)
		}
	}(zipReader)

	var (
		rsaFiles   []string
		sfFiles    []string
		otherFiles []string
	)

	for _, zf := range zipReader.File {
		switch {
		case zf.FileInfo().IsDir():
			continue
		case strings.HasPrefix(zf.Name, "META-INF"):
			f := strings.ToLower(zf.Name)
			switch {
			case strings.HasSuffix(f, ".rsa"):
				rsaFiles = append(rsaFiles, zf.Name)
			case strings.HasSuffix(f, ".sf"):
				sfFiles = append(sfFiles, zf.Name)
			case strings.HasSuffix(f, ".mf"):
				otherFiles = append(otherFiles, zf.Name)
			}
		}
	}
	return append(rsaFiles, append(sfFiles, otherFiles...)...), nil
}

func processPackageLine(line string) (result [3]string) {
	parts := strings.Split(misc.TwoSpotValue(line), " ")
	for _, part := range parts {
		part = strings.ReplaceAll(part, "=", ":")
		switch {
		case strings.HasPrefix(part, "name"):
			result[0] = misc.RemoveQuoteMark(misc.TwoSpotValue(part))
		case strings.HasPrefix(part, "versionCode"):
			result[1] = misc.RemoveQuoteMark(misc.TwoSpotValue(part))
		case strings.HasPrefix(part, "versionName"):
			result[2] = misc.RemoveQuoteMark(misc.TwoSpotValue(part))
		}
	}
	return
}

func extractPermission(line string) string {
	return misc.RemoveQuoteMark(strings.SplitN(line, "=", 2)[1])
}

func extractLabel(line string) (key, value string) {
	val := "application-label"
	parts := strings.SplitN(line, ":", 2)
	value = misc.RemoveQuoteMark(parts[1])
	if parts[0] == val {
		key = "NoLocale"
		return
	}
	key = parts[0][len(val)+1:]
	return
}

func extractLaunchActivity(line string) string {
	for _, part := range strings.Split(line, " ") {
		if strings.HasPrefix(part, "name='") {
			return strings.Split(part, "'")[1]
		}
	}
	return ""
}

func extractNativeCode(line string) map[string]struct{} {
	result := make(map[string]struct{})

	parts := strings.Split(misc.TwoSpotValue(line), " ")
	for _, val := range parts {
		result[misc.RemoveQuoteMark(val)] = struct{}{}
	}
	return result
}

func resArrName(line string) string {
	rawName := strings.SplitN(line, ":", 3)[1]
	return strings.SplitN(rawName, "/", 2)[1]
}

func resStringName(line string) string {
	return resArrName(line)
}

func resArrValues(source []string) [][2]string {
	result := make([][2]string, len(source))
	for i, val := range source {
		line := strings.TrimSpace(val)
		if !strings.HasPrefix(line, "#") {
			panic("output format was changed")
		}
		parts := strings.SplitN(line, " ", 4)
		values := [2]string{misc.RemoveBraces(parts[2]), misc.RemoveQuoteMark(parts[3])}
		result[i] = values
	}
	return result
}

func resStringValue(line string) (result [2]string) {
	line = strings.TrimSpace(line)
	if !strings.HasPrefix(line, "(") {
		panic("out format was changed")
	}
	parts := strings.SplitN(line, " ", 2)
	result[0] = misc.RemoveBraces(parts[0])
	result[1] = misc.RemoveQuoteMark(parts[1])
	return
}
