#!/data/data/com.termux/files/usr/bin/env python3

# Bootstrap Ver: bootstrap-2022.07.17-r1

from platform import machine
import os
import sys
import shutil
import subprocess
import tempfile
import shlex
from zipfile import ZipFile
import hashlib

# Machine Arch
arch = machine()

# Bootstrap
bootstrap_ver = "bootstrap-2022.07.17-r1 Pacman"
bootstrap_baselink = "https://github.com/termux-pacman/termux-packages/releases/download/bootstrap-2022.07.17-r1/bootstrap-{0}.zip"

bootstrap_sha256 = {'aarch64': '4fb0779953412ce1bc6a2bef85cb6ce30c8f93bbf59ae33a7a9f758b578f0402', 'arm': '0873419780ee3615f280a305448d03240700e445732dd482652130fcb000b9b9', 'i686': '3a7fee15de02aa49ae81262a24a699d33837b39588d50fde99e479d04c885700', 'x86_64': '9a70af7847c700b3bb865f00d1000d777a5528e4dd8ead68c47ed52affcf75e7'}

# Glibc Link
glibc_link = "https://github.com/Maxython/glibc-for-termux/releases/download/20220711/gpft-20220711-aarch64.tar.xz"
glibc_script = f"""#!/data/data/com.termux/files/usr/bin/bash
# Glibc Install
# Thanks, Maxython

echo "WARNING: EXPERIMENTAL"

pacman -Syy 2>&1 > /dev/null
if pkg install wget --noconfirm --quiet --needed && wget -O /tmp/glibc.tar.xz https://github.com/Maxython/glibc-for-termux/releases/download/20220711/gpft-20220711-aarch64.tar.xz ; then
	echo "Installing..."
else
	echo "Something gone wrong"
	exit
fi

PWD=$(pwd)

cd /tmp/
tar xJf glibc.tar.xz

if pacman -U --noconfirm glibc-for-termux/* ; then
	echo "Installed!"
else
	echo "Something gone wrong"
	exit
fi

rm -rf glibc*

cd $PWD
echo "Use grun --shell for shell with custom commands, or use grun ./binary_file to.run glibc binaries"
echo "More info at: https://github.com/Maxython/glibc-for-termux"
"""

# Variables
base_dir = f"{os.environ['PREFIX']}/var/lib"
program_dir = f"{base_dir}/termux_install"
chroot_dir = f"{program_dir}/pacman-chroot64"
exec_dir = os.getcwd()

help_text = """termux-pacman-install64 - Install 64 bit Termux chroot on your machine
-----
This program is needed to install Termux chroot from base Termux bootstrap located at https://github.com/termux/termux-packages/releases
Bootstrap version: %s
Chroot installed to %s
-----
Flags:
    -h  Show help
    -f  Force install up on existing chroot
    -r  Reinstall chroot | REMOVES ALL DATA!
    -i  Standart install of chroot"""

# Check up args.
if len(sys.argv) > 1: # If has arg...
	flag = sys.argv[1] # Parse it
else: # If no arg...
	flag = "-i" # Then, just use install arg.

if flag == "-h": # Help text
	print(help_text % (bootstrap_ver, chroot_dir)) # Insert version and path
	sys.exit()

if flag not in ["-i", "-r", "-f"]: # Show error, help and when exit.
	print(f"ERROR: Unknown argument passed - '{flag}'\n")
	print(help_text % (bootstrap_ver, chroot_dir))
	sys.exit()

# Functions
# Setup additional files
def setup_files():
	with open(f"{chroot_dir}/usr/etc/motd") as f: motd = f.read().replace("Termux!", f"Termux-Install {arch.upper()} Container!\nVersion: {bootstrap_ver}", 1)
	motd += "Termux-Install on GitHub: https://github.com/KrutosVIP/TermuxInstall\n\n"
	motd = motd.replace("at https://termux.dev/issues", "at Termux-Install GitHub", 1)
	with open(f"{chroot_dir}/usr/etc/motd", "w") as f: f.write(motd)

	with open(f"{chroot_dir}/usr/etc/termux.install", "w") as f: f.write(f'export BOOTSTRAP_VERSION="{bootstrap_ver}"')
	with open(f"{chroot_dir}/usr/bin/termux-install-glibc", "w") as f: f.write(glibc_script)
	shell(f"chmod 0700 {chroot_dir}/usr/bin/termux-install-glibc")

# shell command, pass arg as normal command. Returns result code.
def shell(command):
	return subprocess.run(shlex.split(command), stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT).returncode
# Wget wrapper
def wget(link, output):
	return shell(f"wget {link} -O {output}")

# Setup rchmod on all dirs in list
def setup_perms(dirs, mode):
	os.chdir(f"{chroot_dir}/usr")
	for dir in dirs:
		recursive_chmod(dir, mode)
	os.chdir(exec_dir)

	return 0

# Symlinks creator
def symlink(file):
	os.chdir(f"{chroot_dir}/usr")

	with open(file) as f: # Read SYMLINKS.txt from unpacked Bootstrap
		symlinks = f.read().split("\n") # Read all file and split by \n

	if symlinks[-1] == "": symlinks.pop() # Remove last "" in list

	os.remove(file) # Remove file

	for link in symlinks: # For symlink in symlinks
		link = link.split("←") # Split by this symbol

		# Symlinks in this file represented like this:
		# coreutils←./bin/mktemp
		# So we need to make symlink from coreutils to ./bin/mktemp, right?
		# No, we need to make symlink from ./bin/coreutils to ./bin/mktemp. And thats why the code looks so complex.
		if os.path.islink(link[1]): os.remove(link[1])

		os.symlink(f"{chroot_dir}/usr/" + os.path.join(os.path.dirname(link[1]), link[0]), link[1])

	os.chdir(exec_dir) # Goto execution dir

	return 0

# Recursive Chmod on dir and files
def recursive_chmod(dir, mode):
	shell(f"chmod {mode} {dir} -R")
	shell(f"chmod {mode} {dir}")
	return 0

# Unzip archive
def unzip(archive, out):
	try:
		with ZipFile(archive) as zip:
			zip.extractall(out)
	except Exception as e:
		return 1

	return 0

# SHA256 Check
def check_integrity(file, sum):
	BUFFER = 65536 # 64KB Buffer
	sha256 = hashlib.sha256()

	with open(file, "rb") as f: # Read file by chunks
		while True:
			data = f.read(BUFFER)
			# End of data? Stop.
			if not data: break

			sha256.update(data)

	sha256 = sha256.hexdigest()

	if sum == sha256:
		return 0

	return 1

# All checks
if (not flag in ["-f", "-r"]) and (os.path.isdir(chroot_dir)):
	print("ERROR: Chroot dir exists. Use flag -r if you want to reinstall chroot or use termux-pacman-remove64 to remove it")
	sys.exit()
elif (flag == "-r") and (os.path.isdir(chroot_dir)):
	shutil.rmtree(chroot_dir)

# Select arch

# Support was not really checked.
if arch in ["x86_64", "AMD64"]:
	print("WARNING: Experimental feature.")
	arch = "x86_64"

elif arch in ["aarch64", "armv8l", "armv8l", "armv9l", "armv9h", "armv9"]:
	arch = "aarch64"

elif arch in ["arm", "i686", "armv7l", "armv7h"]:
	print("ERROR: Unable to install 64-bit chroot on 32-bit machine.")
	sys.exit(0)

else:
	print("ERROR: Unknown arch")
	sys.exit(0)

# Format bootstrap link
bootstrap_link = bootstrap_baselink.format(arch)

print(f"""-----
Installing Termux Bootstrap {bootstrap_ver} for {arch}
To: {chroot_dir}
-----""")

# Create temp dir
with tempfile.TemporaryDirectory() as work_dir:
	bootstrap_file = f"{work_dir}/bootstrap.zip"

	# Download file using wget
	print(f"> Downloading bootstrap...")
	if wget(bootstrap_link, bootstrap_file):
		print("ERROR: Something gone wrong. Stop.")
		sys.exit(0)

	print(f"> Checking integrity...")
	if check_integrity(bootstrap_file, bootstrap_sha256[arch]):
		print("ERROR: Something gone wrong. Stop.")
		sys.exit(0)

	print(f"> Unpacking bootstrap to Chroot Dir...")
	if unzip(bootstrap_file, f"{chroot_dir}/usr"):
		print("ERROR: Something gone wrong. Stop.")
		sys.exit(0)
	if not os.path.isdir(f"{chroot_dir}/home"): os.mkdir(f"{chroot_dir}/home")

	print("> Setting up symlinks...")
	symlink(f"{chroot_dir}/usr/SYMLINKS.txt")

	print("> Setting up permissions...")
	setup_perms(["./bin", "./libexec", "./lib/apt/apt-helper", "./lib/apt/methods"], "0700")

	setup_files()

	print("Done! Use termux-pacman-chroot64 in this dir to get in chroot.")


