"""
* SPDX-FileCopyrightText: 2023-2025 PeppermintOS Team
* (peppermintosteam@proton.me)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Set the infrastructure for bubbles to begin the ISO build
* This copies needed config files to the binary and chroot
* locations, based on the build base and architecture.
"""
import os
import collections
from pathlib import Path
import shutil
from python_modules.logger_modules import builder_logger as logger
from python_modules.paths_modules import (HOME_FOLDER, WPCHROOT,
    BINARYPTH, BOOTSTRAP_FOLDER, FUSATOCONFIG, allowed_bases,
    symlinks, copyfolderfiles, copyfilesspecified)


def copy_multimedia_files(sbase, sarch):
    """
    Copy the multimedia to the ARCHIVES folder depending on 
    the architecture. It will copy folders as needed.
    Args:
    sbase (str): Base architecture could be ("deb" or "dev")
    sarch (str): Architecture specifics could be ("32" or "64")
    """
    logger.info("Copy multimedia Archive")
    src_archive = f'/multimedia/{sbase}{sarch}'
    des_archive = '/archives'
    source_path = HOME_FOLDER + src_archive
    dest_path = HOME_FOLDER + '/' + FUSATOCONFIG + des_archive
    logger.info("Source path: %s", source_path)
    logger.info("Destination path: %s", dest_path)
    try:
        shutil.copytree(source_path, dest_path, dirs_exist_ok=True)
        logger.info("Successfully copied files from %s to %s",
            source_path, dest_path)
    except Exception as _:
        logger.error("Error copying files: %s", str(_), exc_info=True)
        raise
        exit()
    logger.info("Archive copy completed")


def copy_binary_folders(sbase, sarch):
    """
    Copy all the needed folders to BINARY depending on the architecture.
    """
    logger.info("Starting binary folder copy process")
    folder_pairs = [
        (f'splash/{sbase}{sarch}/boot', 'boot'),
        (f'splash/{sbase}{sarch}/isolinux', 'isolinux'),
        (f'splash/{sbase}_live-theme', 'boot/grub'),
        (f'splash/{sbase}_splash', 'isolinux'),
        (f'splash/{sbase}_splash', 'boot/grub')
    ]
    for src, dest in folder_pairs:
        source_path = os.path.join(HOME_FOLDER, src)
        dest_path = os.path.join(HOME_FOLDER, BINARYPTH, dest)
        logger.info("Copying from %s to %s", source_path, dest_path)
        try:
            shutil.copytree(source_path, dest_path, dirs_exist_ok=True)
            logger.info("Successfully copied to %s", dest_path)
        except(ValueError, TypeError) as _:
            logger.error("Error copying to %s: %s", dest_path, str(_))
            exit()
    logger.info("Binary folder copy process completed")


def copy_fusato_configs(sbase, sarch):
    """
    Copy all the needed files to the hooks folders depending on
    the architecture.
    """
    logger.info("Starting Fusato config copy process")
    source = f'/hooks/normal/{sbase}{sarch}'
    destination = '/hooks/normal/'
    source_path = HOME_FOLDER + source + '/'
    dest_path = (
        Path(HOME_FOLDER) / Path(FUSATOCONFIG) / destination.lstrip('/'))
    logger.info("Copying from %s to %s", source_path, dest_path)
    try:
        shutil.copytree(source_path, dest_path, dirs_exist_ok=True)
        logger.info("Successfully copied Fusato configs to %s",
            dest_path)
    except (ValueError, TypeError) as _:
        logger.error("Error copying Fusato configs to %s: %s",
            dest_path, str(_))
        exit()
    logger.info("Fusato config copy process completed")


def copy_server_config_files(base):
    """
    Copies server initial config files to CHROOT depending on the base.
    """
    if base not in allowed_bases:
        logger.warning("Base '%s' is not allowed. Skipping.", base)
        return
    logger.info("Copy Server Files for base: %s", base)
    server_path = f'/server/scripts/{base}/'
    file_paths = [
        'welcome.sh',
        'configure_apache2.sh',
        'configure_firewalld.sh',
        'configure_hostname.sh',
        'configure_mariadb.sh',
        'configure_nginx.sh',
        'configure_php_and_docker.sh',
        'configure_postfix.sh',
        'configure_postgresql.sh',
        'configure_sqlite.sh',
        'configure_ssh.sh',
        'configure_static_ip.sh',
        'create_user.sh',
        'update_and_install.sh'
    ]
    destination = '/usr/local/bin'
    full_dest_path = (
        Path(HOME_FOLDER) / Path(WPCHROOT) / destination.lstrip('/'))
    full_dest_path.mkdir(parents=True, exist_ok=True)
    logger.info("Ensured directory exists: %s", full_dest_path)
    for file in file_paths:
        src_path = Path(HOME_FOLDER) / server_path.lstrip('/') / file
        dest_path = full_dest_path / file
        logger.info("Copying %s to %s", src_path, dest_path)
        try:
            if src_path.exists():
                if src_path.is_dir():
                    shutil.copytree(src_path, dest_path,
                    dirs_exist_ok=True)
                else:
                    shutil.copy2(src_path, dest_path)
                logger.info("Successfully copied to %s", dest_path)
            else:
                logger.error("Source path does not exist: %s", src_path)
        except (ValueError, TypeError) as _:
            logger.error(
                "Error copying %s to %s: %s", src_path, dest_path, _)
            exit()
    logger.info(
        "Completed copying server config files for base: %s", base)


def copy_architecture_files(sbase, sarch, force_copy=False):
    """ 
    Copy all the needed files and folders to CHROOT. Depending on the
    architecture, it will copy files and folders as needed.
    """
    logger.debug("Starting copy process for architecture-specific files")
    sources_path = '/sources/'
    file_pairs = [
        (f'{sources_path}{sbase}{sarch}/sources.list',
         f'/opt/pepconf/sources.list'),
        ('/id_files/pep_id', '/usr/share/peppermint/pep_id'),
        (f'/osrelease/{sbase}{sarch}/os-release', '/usr/lib/os-release'),
        (f'/osrelease/{sbase}{sarch}/os-release', '/opt/pepconf/os-release'),
        (f'/grub/{sbase}{sarch}/grub', '/etc/default/grub'),
        (f'/grub/{sbase}_themes', '/boot/grub/themes')
    ]
    for src, dest in file_pairs:
        src_path = Path(HOME_FOLDER) / src.lstrip('/')
        dest_path = (
            Path(HOME_FOLDER) / Path(WPCHROOT) / dest.lstrip('/'))
        if dest_path.exists() and not force_copy:
            logger.info(
            "Skipping %s as it already exists at %s",
            src_path, dest_path)
            continue
        logger.info("Copying %s to %s", src_path, dest_path)
        try:
            if src_path.is_dir():
                shutil.copytree(src_path, dest_path, symlinks=True,
                ignore_dangling_symlinks=True, dirs_exist_ok=True)
            else:
                dest_path.parent.mkdir(parents=True, exist_ok=True)
                shutil.copy2(src_path, dest_path)
        except (ValueError, TypeError) as _:
            logger.error("Error copying %s to %s: %s", src_path,
                dest_path, _)
            exit()
        else:
            logger.info("Successfully copied %s to %s", src_path,
                dest_path)
    logger.debug("Architecture-specific file copy process completed")


def get_id_build_type():
    """
    This will get the type of build that is taking place and copy 
    relevant files.
    """
    logger.debug("Starting the build type identification process")
    source_folder = os.path.expanduser(f'{HOME_FOLDER}/build_type')
    dest_folder = os.path.join(os.path.expanduser('~'), 'bubbles',
        'iso_configs', 'fusato', 'config', 'includes.chroot', 'opt',
        'pepconf'
    )
    logger.info("Source folder: %s", source_folder)
    logger.info("Destination folder: %s", dest_folder)
    try:
        os.makedirs(dest_folder, exist_ok=True)
        logger.info("Ensured destination folder exists: %s",
            dest_folder)
    except (ValueError, TypeError) as _:
        logger.error("Failed to create destination folder: %s", str(_))
        exit()
        return
    files_copied = 0
    for filename in os.listdir(source_folder):
        src_file = os.path.join(source_folder, filename)
        dest_file = os.path.join(dest_folder, filename)
        if os.path.isfile(src_file):
            try:
                shutil.copy(src_file, dest_file)
                logger.info('Successfully copied: %s to %s', src_file,
                dest_file)
                files_copied += 1
            except (ValueError, TypeError) as _:
                logger.error("Failed to copy %s to %s: %s", src_file,
                dest_file, str(_))
                exit()
        else:
            logger.warning("Skipped non-file item: %s", src_file)

    logger.info("Build type identification process completed. %d files "
        "copied.", files_copied)


def ignore_missing_files(src, names):
    """
    This will keep the build going even if files are missing from from 
    the confiigs
    """
    logger.info("Checking for missing files in directory: %s", src)
    missing_files = []
    for name in names:
        full_path = os.path.join(src, name)
        if not os.path.exists(full_path):
            missing_files.append(name)
            logger.warning("File not found: %s", full_path)
    if missing_files:
        logger.info("Total missing files: %d", len(missing_files))
    else:
        logger.info("No missing files found in %s", src)
    return missing_files


def add_web_profile():
    """
    This will move the web profile depending on the build type.
    """
    logger.debug("Starting to copy Web Profiles")
    path_to_bldtype_file = os.path.expanduser('~/start/bldtype')
    lw_src_path = '/browser_profiles/lw/'
    ff_src_path = '/browser_profiles/ff/'
    des_src_path = '/etc/skel/.local/share/pmostools'
    build_id_list = [
        os.path.join(path_to_bldtype_file, f"{base}.{arch}{desktop}")
        for base in ['deb', 'dev']
        for arch, desktop in [('64', 'xfc'), ('arm', 'xfc'),
            ('64', 'gfb'), ('64', 'opb')
            ]
    ]
    profile_copied = False
    for build_id in build_id_list:
        if os.path.exists(build_id):
            logger.info(
                "Found build id file: %s. Copying lw profile.",
                build_id)
            try:
                shutil.copytree(
                    os.path.join(HOME_FOLDER, lw_src_path.lstrip('/')),
                    os.path.join(HOME_FOLDER, WPCHROOT.lstrip('/'),
                    des_src_path.lstrip('/')),
                    dirs_exist_ok=True,
                    ignore=ignore_missing_files
                )
                logger.info("Successfully copied lw profile")
                profile_copied = True
                break
            except (ValueError, TypeError) as _:
                logger.error("Error copying lw profile: %s", str(_))
                exit()
    if not profile_copied:
        logger.info("No matching build file found. Copying ff profile.")
        try:
            shutil.copytree(
                os.path.join(HOME_FOLDER, ff_src_path.lstrip('/')),
                os.path.join(
                    HOME_FOLDER, WPCHROOT.lstrip('/'),
                    des_src_path.lstrip('/')),
                dirs_exist_ok=True,
                ignore=ignore_missing_files
            )
            logger.info("Successfully copied ff profile")
        except (ValueError, TypeError) as _:
            logger.error("Error copying ff profile: %s", str(_))
            exit()

    logger.debug("Web profile copying process completed")


def set_symlinks():
    """
    Set the symlinks that are used for all builds.
    """
    logger.info("Starting to set symlinks for all builds")

    for target_path, source in symlinks.items():
        full_target_path = os.path.join(HOME_FOLDER,
            WPCHROOT.lstrip('/'), target_path.lstrip('/'))
        logger.info("Creating symlink: %s -> %s", full_target_path,
            source)
        try:
            if os.path.islink(full_target_path):
                os.unlink(full_target_path)
                logger.info("Removed existing symlink: %s",
                    full_target_path)
            os.makedirs(os.path.dirname(full_target_path),
                exist_ok=True)
            os.symlink(source, full_target_path)
            logger.info("Successfully created symlink: %s -> %s",
                full_target_path, source)
        except FileExistsError:
            logger.warning(
                "Symlink already exists and is not a symbolic link: %s",
                    full_target_path)
            exit()
        except PermissionError:
            logger.error(
                "Permission denied when creating symlink: %s",
                    full_target_path)
            exit()
        except (ValueError, TypeError) as _:
            logger.error("Error creating symlink %s -> %s: %s",
                full_target_path, source, str(_))
            exit()
    logger.info("Finished setting symlinks for all builds")


def icons_themes():
    """
    Copy icons and themes for all builds using paths defined in
    copyfolderfiles.
    """
    logger.debug("Starting to copy icons and themes")
    copy_paths = [
        ("SRC_DEBIAN_DARK", "DES_THEMES"),
        ("SRC_MANJARO_DARK", "DES_THEMES"),
        ("SRC_PEPPERMINT_DARK", "DES_THEMES"),
        ("SRC_DEBIAN", "DES_THEMES"),
        ("SRC_MANJARO", "DES_THEMES"),
        ("SRC_PEPPERMINT", "DES_THEMES"),
        ("SRC_TELA_BLUE_DARK", "DES_ICONS"),
        ("SRC_TELA_GREEN_DARK", "DES_ICONS"),
        ("SRC_TELA_RED_DARK", "DES_ICONS"),
        ("SRC_TELA_BLUE_BASE", "DES_ICONS"),
        ("SRC_TELA_GREEN_BASE", "DES_ICONS"),
        ("SRC_TELA_RED_BASE", "DES_ICONS"),
        ("SRC_TELA", "DES_ICONS"),
    ]
    for src_key, dest_key in copy_paths:
        if src_key in copyfolderfiles and dest_key in copyfolderfiles:
            src = copyfolderfiles[src_key].strip()
            dest = copyfolderfiles[dest_key].strip()
            source_path = Path(HOME_FOLDER) / src.lstrip('/')
            dest_path = Path(HOME_FOLDER) / WPCHROOT / dest.lstrip('/')
            folder_name = Path(src).name
            full_dest_path = dest_path / folder_name
            logger.info("Copying from %s to %s", source_path,
                full_dest_path)
            try:
                shutil.copytree(source_path, full_dest_path,
                    dirs_exist_ok=True)
                logger.info("Successfully copied %s to %s",
                    src_key, dest_key)
            except (ValueError, TypeError) as _:
                logger.error("Error copying %s to %s: %s", src_key,
                    dest_key, str(_))
                exit()
        else:
            logger.warning(
                "Skipping copy for %s to %s: Keys not found in"
                " copyfolderfiles", src_key, dest_key)
    logger.debug("Finished copying icons and themes")


def shared_files():
    """
    Copy all specific files that are used for all builds.
    """
    logger.debug("Starting to copy shared files")
    copy_pairs = [
        ("SRC_ALIAS", "DES_ALIAS"),
        ("SRC_XDAILY", "DES_XDAILY"),
        ("SRC_PEPREPO", "DES_PEPREPO"),
        ("SRC_GPG_BINARY", "DES_GPG_BINARY"),
        ("SRC_GPG_CHROOT", "DES_GPG_CHROOY"),
        ("SRC_XDAILYGUI", "DES_XDAILYGUI"),
        ("SRC_SUGGESTED", "DES_SUGGESTED"),
        ("SRC_PFETCH", "DES_PFETCH"),
        ("SRC_WELCOME", "DES_WELCOME"),
        ("SRC_KUMO", "DES_KUMO"),
        ("SRC_LIGHTDM", "DES_LIGHTDM"),
        ("SRC_LIGHTDM_GREETER", "DES_LIGHTDM_GREETER"),
        ("SRC_PLY", "DES_PLY"),
    ]
    for src_key, des_key in copy_pairs:
        if src_key in copyfilesspecified and des_key in copyfilesspecified:
            source = copyfilesspecified[src_key].strip()
            destination = copyfilesspecified[des_key].strip()
            source_path = Path(HOME_FOLDER) / source.lstrip('/')
            dest_path = (
                Path(HOME_FOLDER) / WPCHROOT / destination.lstrip('/')
                )
            logger.info(
                "Attempting to copy: %s to %s", source_path, dest_path)
            try:
                dest_path.parent.mkdir(parents=True, exist_ok=True)
                shutil.copy2(source_path, dest_path)
                logger.info("Successfully copied: %s to %s",
                    source_path, dest_path)
                if des_key in ["DES_GPG_BINARY", "DES_GPG_CHROOT"]:
                    os.chmod(dest_path, 0o644)
                    logger.info("Set permissions to 644 for %s", dest_path)
            except FileNotFoundError:
                logger.error("Source file not found: %s", source_path)
                exit()
            except PermissionError:
                logger.error("Permission denied when copying to: %s",
                    dest_path)
                exit()
            except (ValueError, TypeError) as _:
                logger.error("Error copying %s to %s: %s", source_path,
                    dest_path, str(_))
                exit()
        else:
            logger.warning(
                "Skipping copy for %s to %s: Keys not found in"
                " copyfilesspecified", src_key, des_key)
    logger.info("Finished copying shared files")


def setup_hooks_minis():
    """
    Copy all hooks files that are used for mini builds.
    """
    logger.debug("Starting to copy hooks files")
    copy_pairs = [
        ("SRC_HOOKS_MINI_NORMAL", "DES_HOOKS_MINI_NORMAL")
    ]
    for src_key, des_key in copy_pairs:
        if src_key in copyfilesspecified and des_key in copyfilesspecified:
            source = copyfilesspecified[src_key].strip()
            destination = copyfilesspecified[des_key].strip()
            source_path = Path(HOME_FOLDER) / source.lstrip('/')
            dest_path = (
                Path(HOME_FOLDER) / destination.lstrip('/')
                )
            logger.info(
                "Attempting to copy: %s to %s", source_path, dest_path)
            try:
                dest_path.parent.mkdir(parents=True, exist_ok=True)
                shutil.copy2(source_path, dest_path)
                logger.info("Successfully copied: %s to %s",
                    source_path, dest_path)
            except FileNotFoundError:
                logger.error("Source file not found: %s", source_path)
                exit()
            except PermissionError:
                logger.error("Permission denied when copying to: %s",
                    dest_path)
                exit()
            except (ValueError, TypeError) as _:
                logger.error("Error copying %s to %s: %s", source_path,
                    dest_path, str(_))
                exit()
        else:
            logger.warning(
                "Skipping copy for %s to %s: Keys not found in"
                " copyfilesspecified", src_key, des_key)
    logger.info("Finished copying Hook files")


def setup_hooks():
    """
    Copy all hooks files that are used for all builds minus the mini.
    """
    logger.debug("Starting to copy hooks files")

    copy_pairs = [
        ("SRC_HOOKS_LIVE", "DES_HOOKS_LIVE"),
        ("SRC_HOOKS_NORMAL", "DES_HOOKS_NORMAL")
    ]
    for src_key, des_key in copy_pairs:
        if src_key in copyfilesspecified and des_key in copyfilesspecified:
            source = copyfilesspecified[src_key].strip()
            destination = copyfilesspecified[des_key].strip()
            source_path = Path(HOME_FOLDER) / source.lstrip('/')
            dest_path = (
                Path(HOME_FOLDER) / destination.lstrip('/')
                )
            logger.info(
                "Attempting to copy: %s to %s", source_path, dest_path)
            try:
                dest_path.parent.mkdir(parents=True, exist_ok=True)
                shutil.copy2(source_path, dest_path)
                logger.info("Successfully copied: %s to %s",
                    source_path, dest_path)
            except FileNotFoundError:
                logger.error("Source file not found: %s", source_path)
                exit()
            except PermissionError:
                logger.error("Permission denied when copying to: %s",
                    dest_path)
                exit()
            except (ValueError, TypeError) as _:
                logger.error("Error copying %s to %s: %s", source_path,
                    dest_path, str(_))
                exit()
        else:
            logger.warning(
                "Skipping copy for %s to %s: Keys not found in"
                " copyfilesspecified", src_key, des_key)
    logger.info("Finished copying Hook files")


def shared_server_files():
    """ 
    This will copy all specific files that are used for the server builds.
    """
    logger.info("Starting to copy shared server files")
    src_paths = ('/server/firewall/public.xml',
                 )
    des_paths = ('/etc/firewalld/zones',
                 )
    src_q = collections.deque(src_paths)
    des_q = collections.deque(des_paths)
    size_q = len(src_q)
    logger.info("Preparing to copy %d files", size_q)
    for size_length in range(size_q):
        source = src_q.popleft()
        des = des_q.popleft()
        full_source_path = HOME_FOLDER + source
        full_dest_path = HOME_FOLDER + WPCHROOT + des
        logger.info("Copying file %d of %d", size_length + 1, size_q)
        logger.info("Source: %s", full_source_path)
        logger.info("Destination: %s", full_dest_path)
        try:
            shutil.copy(full_source_path, full_dest_path)
            logger.info(
                "Successfully copied file to %s", full_dest_path)
        except FileNotFoundError:
            logger.error(
                "Source file not found: %s", full_source_path)
            exit()
        except PermissionError:
            logger.error("Permission denied when copying to: %s",
                full_dest_path)
            exit()
        except IOError as _:
            logger.error(
                "I/O error occurred while copying %s to %s: %s",
                full_source_path, full_dest_path, str(_))
            exit()
    logger.info("Completed copying shared server files")


def boostrap_shared():
    """ 
    Copy specific folders in the bootstrap location
    """
    logger.debug("Starting to copy shared bootstrap files")
    src_paths = ('issue',)
    des_paths = ('etc',)
    src_q = collections.deque(src_paths)
    des_q = collections.deque(des_paths)
    size_q = len(src_q)
    logger.info("Preparing to copy %d directories", size_q)
    for size_length in range(size_q):
        source = src_q.popleft()
        des = des_q.popleft()
        full_source_path = os.path.join(HOME_FOLDER, source)
        full_dest_path = os.path.join(HOME_FOLDER, BOOTSTRAP_FOLDER, des)
        logger.info("Copying directory %d of %d", size_length + 1,
            size_q)
        logger.info("Source: %s", full_source_path)
        logger.info("Destination: %s", full_dest_path)
        try:
            shutil.copytree(
                full_source_path, full_dest_path, dirs_exist_ok=True)
            logger.info("Successfully copied directory to %s",
                full_dest_path)
        except FileNotFoundError:
            logger.error("Source directory not found: %s",
                full_source_path)
            exit()
        except PermissionError:
            logger.error("Permission denied when copying to: %s",
                full_dest_path)
            exit()
        except shutil.Error as _:
            logger.error("Error occurred while copying %s to %s: %s",
                full_source_path, full_dest_path, str(_))
            exit()
    logger.debug("Completed copying shared bootstrap files")


def shared_folders():
    """
    Copy shared folders that are common amongst all the builds.
    """
    logger.debug("Starting to copy shared folders")

    copy_pairs = [
        ("SRC_PLY_LINES", "DES_PLY_LINES"),
        ("SRC_APPS", "DES_APPS"),
        ("SRC_FONT", "DES_FONT"),
        ("SRC_ISSUE", "DES_ISSUE"),
        ("SRC_BUILD_TYPE", "DES_BUILD_TYPE"),
        ("SRC_ISSUE", "DES_ISSUES_OPT"),
        ("SRC_POLKIT", "DES_POLKIT"),
        ("SRC_USER_CONFIGS", "DES_USER_CONFIGS"),
        ("SRC_PIXMAPS", "DES_PIXMAPS"),
        ("SRC_WALLPAPER", "DES_WALLPAPER"),
        ("SRC_MENU", "DES_MENU"),
        ("SRC_FACE", "DES_FACE"),
        ("SRC_PMOSTOOLS", "DES_PMOSTOOLS"),
        ("SRC_AUTO_START", "DES_AUTO_START"),
        ("SRC_PYLIBS", "DES_PYLIBS"),
    ]
    for src_key, des_key in copy_pairs:
        if src_key in copyfolderfiles and des_key in copyfolderfiles:
            source = copyfolderfiles[src_key].strip()
            destination = copyfolderfiles[des_key].strip()
            source_path = Path(HOME_FOLDER) / source.lstrip('/')
            dest_path = (
                Path(HOME_FOLDER) / WPCHROOT / destination.lstrip('/')
                )
            logger.info("Attempting to copy folder: %s to %s",
                source_path, dest_path)
            try:
                shutil.copytree(source_path, dest_path,
                    dirs_exist_ok=True)
                logger.info("Successfully copied folder: %s to %s",
                    source_path, dest_path)
            except FileNotFoundError:
                logger.error("Source folder not found: %s",
                    source_path)
                exit()
            except PermissionError:
                logger.error(
                    "Permission denied when copying to: %s",
                    dest_path)
                exit()
            except (ValueError, TypeError) as _:
                logger.error("Error copying folder %s to %s: %s",
                    source_path, dest_path, str(_))
                exit()
        else:
            logger.warning(
                    "Skipping copy for %s to %s: Keys not found in "
                    "copyfolderfiles", src_key, des_key)
    logger.info("Finished copying shared folders")
    get_id_build_type()


def loaded_folders():
    """ 
    This function will get the files that are used by the loaded builds.
    """
    logger.debug("Starting to copy loaded folders")
    src_paths = ('/loaded/application',
                 '/loaded/wallpaper')
    des_paths = ('/usr/share/applications',
                 '/usr/share/backgrounds')
    src_q = collections.deque(src_paths)
    des_q = collections.deque(des_paths)
    size_q = len(des_q)
    logger.info("Preparing to copy %d directories", size_q)
    for size_length in range(size_q):
        source = src_q.popleft()
        des = des_q.popleft()
        full_source_path = HOME_FOLDER + source
        full_dest_path = HOME_FOLDER + '/' + WPCHROOT + des
        logger.info("Copying directory %d of %d", size_length + 1,
            size_q)
        logger.info("Source: %s", full_source_path)
        logger.info("Destination: %s", full_dest_path)
        try:
            shutil.copytree(full_source_path, full_dest_path,
                dirs_exist_ok=True)
            logger.info(
                "Successfully copied directory from %s to %s",
                full_source_path, full_dest_path)
        except FileNotFoundError:
            logger.error("Source directory not found: %s",
                full_source_path)
            exit()
        except PermissionError:
            logger.error("Permission denied when copying to: %s",
                full_dest_path)
            exit()
        except shutil.Error as _:
            logger.error("Error occurred while copying %s to %s: %s",
                full_source_path, full_dest_path, str(_))
            exit()
    logger.debug("Completed copying loaded folders")