# -*- coding: utf-8 -*-
#  _____  ____   _               _
# |_   _|| __ ) | |  ___    ___ | | __
#   | |  |  _ \ | | / _ \  / __|| |/ /
#   | |  | |_) || || (_) || (__ |   <
#   |_|  |____/ |_| \___/  \___||_|\_\
#
# Copyright (C) 2021-2025 Camelia Lavender <camelia@tblock.me>

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

# Standard libraries
import tarfile
import os
import sys

# External imports
from tblock import Path
import tblock.const
import tblock.filters
import tblock.compat
import tblock.utils

# Local imports
from ..config import set_setting, get_setting, GUISettings
from ..const import PATH_GUI, FILTER_LISTS_ICON_PACK_URL
from ..utils import write_logs


def run() -> None:
    """
    Start the helper
    """
    logging_enabled = get_setting(GUISettings.LOGGING_ENABLED.value)
    logging_enabled = (
        bool(int(logging_enabled)) if logging_enabled is not None else False
    )
    write_logs(f"executing: {sys.argv}", logging_enabled)
    # pylint: disable=broad-exception-caught,broad-except
    try:
        parse_args()
    except IndexError:
        write_logs("operation failed: invalid arguments", logging_enabled)
        sys.exit(1)
    except Exception as _err:
        write_logs(f"operation failed: {_err.args[0]}", logging_enabled)
        sys.exit(1)
    else:
        write_logs("operation was successful", logging_enabled)


def parse_args(arguments=None) -> None:
    """
    Parse the arguments
    """
    # pylint: disable=too-many-branches,too-many-statements
    if arguments is None:
        arguments = sys.argv
    if arguments[1] == "init":
        tblock.config.create_dirs()
        tblock.compat.init_db()
    elif arguments[1] == "test-gui":
        sys.exit(0)
    elif arguments[1] == "unlock":
        os.unlink(Path.DB_LOCK)
    elif arguments[1] == "build":
        tblock.hosts.update_hosts(do_not_prompt=True)
    elif arguments[1] == "enable":
        tblock.hosts.enable_protection(do_not_prompt=True)
    elif arguments[1] == "disable":
        tblock.hosts.restore_hosts(do_not_prompt=True)
    elif arguments[1] == "sync":
        tblock.filters.sync_filter_list_repo()
    elif arguments[1] == "download":
        tblock.filters.Filter(arguments[2]).retrieve()
    elif arguments[1] == "subscribe":
        tblock.filters.Filter(arguments[2]).subscribe(
            tblock.const.FilterPermissions(arguments[3])
            if len(arguments) == 4
            else tblock.DEFAULT_PERMISSIONS
        )
    elif arguments[1] == "update":
        tblock.filters.Filter(arguments[2]).update()
    elif arguments[1] == "remove":
        tblock.filters.Filter(arguments[2]).unsubscribe()
    elif arguments[1] == "rm-cache":
        tblock.filters.Filter(arguments[2]).delete_cache()
    elif arguments[1] == "remove-matches":
        # This is an error in tblock module
        # I gotta fix this shit AAAAAAAAA
        # pylint: disable=protected-access
        tblock.filters.__remove_allowed_matches()
    elif arguments[1] == "add":
        tblock.filters.Filter(arguments[2], custom_source=arguments[3]).add_custom(
            custom_syntax=arguments[4] if len(arguments) == 5 else None
        )
    elif arguments[1] == "allow":
        tblock.rules.allow_domains([arguments[2]], do_not_prompt=True)
    elif arguments[1] == "block":
        tblock.rules.block_domains([arguments[2]], do_not_prompt=True)
    elif arguments[1] == "redirect":
        tblock.rules.redirect_domains(
            [arguments[2]], ip=arguments[3], do_not_prompt=True
        )
    elif arguments[1] == "delete":
        tblock.rules.delete_rules(arguments[2:], do_not_prompt=True)
    elif arguments[1] == "icon":
        tblock.utils.fetch_file(
            FILTER_LISTS_ICON_PACK_URL,
            str(),
            os.path.join(tblock.Path.TMP_DIR, "icons.tar.xz"),
            quiet=True,
        )
    elif arguments[1] == "extract":
        if not os.path.isdir(PATH_GUI.REPO_ICONS):
            os.makedirs(PATH_GUI.REPO_ICONS, exist_ok=True)
        with tarfile.open(
            os.path.join(tblock.Path.TMP_DIR, "icons.tar.xz"), "r:xz"
        ) as _a:
            for icon in _a.getmembers():
                try:
                    icon_name = icon.name.split("./")[1]
                    if "/" not in icon_name:
                        with open(
                            os.path.join(PATH_GUI.REPO_ICONS, icon_name), "wb"
                        ) as _fb:
                            _fb.write(_a.extractfile(icon).read())
                    else:
                        raise IndexError()
                except IndexError:
                    write_logs(
                        "tar archive seems corrupted! exiting now since going further would be dangerous!"
                    )
    elif arguments[1] == "setting":
        setting = GUISettings(arguments[2])
        set_setting(setting.value, arguments[3])
    else:
        raise IndexError()
