<?php

require_once __DIR__ . "/AXML.php";
require_once __DIR__ . "/ARSC.php";
require_once __DIR__ . "/IconExtractor.php";

class ApkParser {

    private $zip;
    private $manifestXML;
    private $resources;
    private $apkFile;

    public function __construct($apkFile) {
        $this->apkFile = $apkFile;

        $this->zip = new ZipArchive;
        if ($this->zip->open($apkFile) !== TRUE) {
            throw new Exception("Cannot open APK: $apkFile");
        }

        // Decode AndroidManifest.xml
        $binaryManifest = $this->zip->getFromName("AndroidManifest.xml");
        if (!$binaryManifest) {
            throw new Exception("Missing AndroidManifest.xml");
        }

        $axml = new AXMLParser();
        $this->manifestXML = $axml->decode($binaryManifest);

        // Parse resources.arsc
        $arscData = $this->zip->getFromName("resources.arsc");
        $this->resources = $arscData ? new ARSCParser($arscData) : null;
    }

    private function getManifestSimpleXML() {
        return simplexml_load_string($this->manifestXML);
    }

    public function getPackageName() {
        $xml = $this->getManifestSimpleXML();
        return (string)$xml['package'];
    }

    public function getVersionName() {
        $xml = $this->getManifestSimpleXML();
        return (string)$xml['versionName'];
    }

    public function getVersionCode() {
        $xml = $this->getManifestSimpleXML();
        return (string)$xml['versionCode'];
    }

    public function getMinSdk() {
        $xml = $this->getManifestSimpleXML();
        return (string)$xml->{"uses-sdk"}['minSdkVersion'];
    }

    public function getTargetSdk() {
        $xml = $this->getManifestSimpleXML();
        return (string)$xml->{"uses-sdk"}['targetSdkVersion'];
    }

    public function getAppName() {
        $xml = $this->getManifestSimpleXML();
        $label = (string)$xml->application['label'];

        // If label is a resource reference (@7f0a0000)
        if (strpos($label, "@") === 0 && $this->resources) {
            return $this->resources->resolveStringResource($label);
        }

        return $label ?: "Unknown App";
    }

    public function getPermissions() {
        $xml = $this->getManifestSimpleXML();
        $perms = [];

        foreach ($xml->{'uses-permission'} as $p) {
            $perms[] = (string)$p['name'];
        }

        return $perms;
    }

    public function getPermissionsDetailed() {
        $list = $this->getPermissions();
        $detailed = [];

        foreach ($list as $perm) {
            $detailed[] = [
                "technical" => $perm,
                "friendly"  => $this->friendlyPermissionName($perm)
            ];
        }

        return $detailed;
    }

    private function friendlyPermissionName($perm) {
        static $map = [
            "android.permission.INTERNET" => "Internet access",
            "android.permission.CAMERA" => "Camera access",
            "android.permission.ACCESS_FINE_LOCATION" => "Precise location",
            "android.permission.ACCESS_COARSE_LOCATION" => "Approximate location",
            "android.permission.READ_CONTACTS" => "Read contacts",
            "android.permission.WRITE_CONTACTS" => "Modify contacts",
            "android.permission.RECORD_AUDIO" => "Microphone access",
            "android.permission.READ_EXTERNAL_STORAGE" => "Read storage",
            "android.permission.WRITE_EXTERNAL_STORAGE" => "Write storage",
            "android.permission.BLUETOOTH" => "Bluetooth access",
            "android.permission.BLUETOOTH_ADMIN" => "Bluetooth control",
        ];

        return $map[$perm] ?? "General permission";
    }

    public function getIconBase64() {
        if (!$this->resources) return null;

        $xml = $this->getManifestSimpleXML();
        $iconRef = (string)$xml->application['icon'];

        if (!$iconRef) return null;

        $iconExtractor = new IconExtractor($this->zip, $this->resources);
        return $iconExtractor->extractIconBase64($iconRef);
    }
}