"""
        Удаляет ненужное и сжимает ресурсы что-бы уменьшить размер АПК

Эффективность на проверена на версии 9.0 Beta 7
разница = оригинальный размер апк - патченный размер апк, не учитывая другие патчи

|   Настройка  |     Размер файла      |       Разница       |   %   |
| :----------- | :-------------------: | :-----------------: |  :-:  |
| None         | 17092 bytes - 17.1 MB |         -           |   -   |
| Compress PNG | 17072 bytes - 17.1 MB |   20 bytes - 0.0 MB | 0.11% |
| Remove files | 17020 bytes - 17.0 MB |   72 bytes - 0.1 MB | 0.42% |
| Remove draws | 16940 bytes - 16.9 MB |  152 bytes - 0.2 MB | 0.89% |
| Remove lines | 16444 bytes - 16.4 MB |  648 bytes - 0.7 MB | 3.79% |
| Remove ai vo | 15812 bytes - 15.8 MB | 1280 bytes - 1.3 MB | 7.49% |
| Remove langs | 15764 bytes - 15.7 MB | 1328 bytes - 1.3 MB | 7.76% |
| Все включены | 13592 bytes - 13.6 MB | 3500 bytes - 4.8 MB | 20.5% |

"compress": {
  "enabled": true,
  "remove_language_files": true,                            // удаляет все языки кроме русского и английского
  "remove_AI_voiceover": true,                              // заменяет ИИ озвучку маскота аниксы пустыми mp3 файлами
  "remove_debug_lines": false,                              // удаляет строки `.line n` из smali файлов использованные для дебага
  "remove_drawable_files": false,                           // удаляет неиспользованные drawable-* из директории decompiled/res
  "remove_unknown_files": true,                             // удаляет файлы из директории decompiled/unknown
  "remove_unknown_files_keep_dirs": ["META-INF", "kotlin"], // оставляет указанные директории в decompiled/unknown
  "compress_png_files": true                                // сжимает PNG в директории decompiled/res
}
"""

priority = -1

# imports
import os
import shutil
import subprocess
from tqdm import tqdm
from utils.smali_parser import get_smali_lines, save_smali_lines


# Patch
def remove_unknown_files(config):
    path = "./decompiled/unknown"
    items = os.listdir(path)
    for item in items:
        item_path = f"{path}/{item}"
        if os.path.isfile(item_path):
            os.remove(item_path)
            if config.get("verbose", False):
                tqdm.write(f"Удалён файл: {item_path}")
        elif os.path.isdir(item_path):
            if item not in config["remove_unknown_files_keep_dirs"]:
                shutil.rmtree(item_path)
                if config.get("verbose", False):
                    tqdm.write(f"Удалёна директория: {item_path}")
    return True


def remove_debug_lines(config):
    for root, _, files in os.walk("./decompiled"):
        for filename in files:
            file_path = os.path.join(root, filename)
            if os.path.isfile(file_path) and filename.endswith(".smali"):
                file_content = get_smali_lines(file_path)
                new_content = []
                for line in file_content:
                    if line.find(".line") >= 0:
                        continue
                    new_content.append(line)
                save_smali_lines(file_path, new_content)
            if config.get("verbose", False):
                tqdm.write(f"Удалены дебаг линии из: {file_path}")
    return True


def compress_png(config, png_path: str):
    try:
        assert subprocess.run(
            [
                "pngquant",
                "--force",
                "--ext",
                ".png",
                "--quality=65-90",
                png_path,
            ],
            capture_output=True,
        ).returncode in [0, 99]
        if config.get("verbose", False):
            tqdm.write(f"Сжат файл PNG: {png_path}")
        return True
    except subprocess.CalledProcessError as e:
        tqdm.write(f"Ошибка при сжатии {png_path}: {e}")
        return False


def compress_png_files(config):
    compressed = []
    for root, _, files in os.walk("./decompiled"):
        for file in files:
            if file.lower().endswith(".png"):
                compress_png(config, f"{root}/{file}")
                compressed.append(f"{root}/{file}")
    return len(compressed) > 0 and any(compressed)


def remove_AI_voiceover(config):
    blank = "./resources/blank.mp3"
    path = "./decompiled/res/raw"
    files = [
        "reputation_1.mp3",
        "reputation_2.mp3",
        "reputation_3.mp3",
        "sound_beta_1.mp3",
        "sound_create_blog_1.mp3",
        "sound_create_blog_2.mp3",
        "sound_create_blog_3.mp3",
        "sound_create_blog_4.mp3",
        "sound_create_blog_5.mp3",
        "sound_create_blog_6.mp3",
        "sound_create_blog_reputation_1.mp3",
        "sound_create_blog_reputation_2.mp3",
        "sound_create_blog_reputation_3.mp3",
        "sound_create_blog_reputation_4.mp3",
        "sound_create_blog_reputation_5.mp3",
        "sound_create_blog_reputation_6.mp3",
    ]

    for file in files:
        if os.path.exists(f"{path}/{file}"):
            os.remove(f"{path}/{file}")
            shutil.copyfile(blank, f"{path}/{file}")
            if config.get("verbose", False):
                tqdm.write(f"Файл mp3 был заменён на пустой: {path}/{file}")

    return True


def remove_language_files(config):
    path = "./decompiled/res"
    folders = [
        "values-af",
        "values-am",
        "values-ar",
        "values-as",
        "values-az",
        "values-b+es+419",
        "values-b+sr+Latn",
        "values-be",
        "values-bg",
        "values-bn",
        "values-bs",
        "values-ca",
        "values-cs",
        "values-da",
        "values-de",
        "values-el",
        "values-en-rAU",
        "values-en-rCA",
        "values-en-rGB",
        "values-en-rIN",
        "values-en-rXC",
        "values-es",
        "values-es-rGT",
        "values-es-rUS",
        "values-et",
        "values-eu",
        "values-fa",
        "values-fi",
        "values-fr",
        "values-fr-rCA",
        "values-gl",
        "values-gu",
        "values-hi",
        "values-hr",
        "values-hu",
        "values-hy",
        "values-in",
        "values-is",
        "values-it",
        "values-iw",
        "values-ja",
        "values-ka",
        "values-kk",
        "values-km",
        "values-kn",
        "values-ko",
        "values-ky",
        "values-lo",
        "values-lt",
        "values-lv",
        "values-mk",
        "values-ml",
        "values-mn",
        "values-mr",
        "values-ms",
        "values-my",
        "values-nb",
        "values-ne",
        "values-nl",
        "values-or",
        "values-pa",
        "values-pl",
        "values-pt",
        "values-pt-rBR",
        "values-pt-rPT",
        "values-ro",
        "values-si",
        "values-sk",
        "values-sl",
        "values-sq",
        "values-sr",
        "values-sv",
        "values-sw",
        "values-ta",
        "values-te",
        "values-th",
        "values-tl",
        "values-tr",
        "values-uk",
        "values-ur",
        "values-uz",
        "values-vi",
        "values-zh",
        "values-zh-rCN",
        "values-zh-rHK",
        "values-zh-rTW",
        "values-zu",
        "values-watch",
    ]

    for folder in folders:
        if os.path.exists(f"{path}/{folder}"):
            shutil.rmtree(f"{path}/{folder}")
            if config.get("verbose", False):
                tqdm.write(f"Удалена директория: {path}/{folder}")
    return True


def remove_drawable_files(config):
    path = "./decompiled/res"
    folders = [
        "drawable-en-hdpi",
        "drawable-en-ldpi",
        "drawable-en-mdpi",
        "drawable-en-xhdpi",
        "drawable-en-xxhdpi",
        "drawable-en-xxxhdpi",
        "drawable-ldrtl-hdpi",
        "drawable-ldrtl-mdpi",
        "drawable-ldrtl-xhdpi",
        "drawable-ldrtl-xxhdpi",
        "drawable-ldrtl-xxxhdpi",
        "drawable-tr-anydpi",
        "drawable-tr-hdpi",
        "drawable-tr-ldpi",
        "drawable-tr-mdpi",
        "drawable-tr-xhdpi",
        "drawable-tr-xxhdpi",
        "drawable-tr-xxxhdpi",
        "drawable-watch",
        "layout-watch",
    ]

    for folder in folders:
        if os.path.exists(f"{path}/{folder}"):
            shutil.rmtree(f"{path}/{folder}")
            if config.get("verbose", False):
                tqdm.write(f"Удалена директория: {path}/{folder}")
    return True


def apply(config) -> bool:
    if config["remove_unknown_files"]:
        tqdm.write(f"Удаление неизвестных файлов...")
        remove_unknown_files(config)

    if config["remove_drawable_files"]:
        tqdm.write(f"Удаление директорий drawable-xx...")
        remove_drawable_files(config)

    if config["compress_png_files"]:
        tqdm.write(f"Сжатие PNG файлов...")
        compress_png_files(config)

    if config["remove_language_files"]:
        tqdm.write(f"Удаление языков...")
        remove_language_files(config)

    if config["remove_AI_voiceover"]:
        tqdm.write(f"Удаление ИИ озвучки...")
        remove_AI_voiceover(config)

    if config["remove_debug_lines"]:
        tqdm.write(f"Удаление дебаг линий...")
        remove_debug_lines(config)

    return True
