#!/usr/bin/python3

######################################################################
# Add support to native system to the arkos emulator configuration.
#
# This file is licensed under the BSD license.
#
# 2024-09-10 Tue
# Dov Grobgeld <dov.grobgeld@gmail.com>
#
# Modified by Magicfly (2025-10-23) for robustness in directory creation
# and rsync operations.
# Modified by Magicfly (2025-10-23) change us roms dir
######################################################################

import argparse
import re
from pathlib import Path
import os
import sys

def find_roms_dir():
    '''Look for the rom files'''
    for candidate in ['/roms',
                      '/roms2']:
        if Path(candidate).exists():
            return candidate
    raise RuntimeError('Failed finding rom directory')

def insert_native_system(filename, roms_dir='/roms'):
    filename = Path(filename)
    
    # 1. Check if the file exists (prevent issues with sudo permission or invalid path)
    if not filename.exists():
        raise FileNotFoundError(f"Configuration file not found: {filename}")
        
    with open(filename) as fh:
        ctx = fh.read()

    if re.search('<name>Native</name>', ctx):
        print('Native support already added!')
        return False

    # Dynamically set the command path using the roms_dir variable
    command_path = Path(roms_dir) / 'native' / 'run.sh %ROM%'

    native_system_ctx = f'''  <system>
    <name>Native</name>
    <fullname>Native</fullname>
    <path>{roms_dir}/native/</path>
    <extension>.exec .run .py .lua</extension>
    <command>{command_path}</command>
    <platform>native</platform>
    <theme>native</theme>
  </system>

'''
    # Insert the new system section before the </systemList> tag
    ctx = re.sub('</systemList>', native_system_ctx + r'\g<0>', ctx)
    
    # Create a backup file and write the updated content
    filename.rename(filename.with_suffix('.cfg.bak'))
    with open(filename, 'w') as fh:
        fh.write(ctx)

    return True

def copy_theme(theme_source_dir, theme_dest_dir, override=False):
    theme_source_dir = Path(theme_source_dir)
    theme_dest_dir = Path(theme_dest_dir)

    if not theme_source_dir.exists():
        raise FileNotFoundError(f'Failed finding theme directory. Looked in: "{theme_source_dir}"')

    # 1. Create the destination directory (including parent directories if missing)
    if theme_dest_dir.exists():
        if not override:
            # Raise an exception if directory already exists and override option is not set
            raise RuntimeError(f'Destination theme directory already exists: {theme_dest_dir}')
    else:
        # Use parents=True to create all parent directories
        # Set directory permissions to 755
        theme_dest_dir.mkdir(mode=0o755, parents=True, exist_ok=True) 

    # 2. Run rsync: add '/' at the end of the source path to copy only its contents,
    # and use options to skip owner/group info (--no-o, --no-g)
    # **Important**: os.system’s return value includes an 8-bit left-shifted exit code
    ret = os.system(f'rsync -av --no-D --no-o --no-g {theme_source_dir}/ {theme_dest_dir}/')
    if (ret >> 8) > 0:
        raise RuntimeError(f'Failed rsyncing the theme directory. Exit code: {ret >> 8}')

def create_roms_directory(roms_dir):
    roms_dir = Path(roms_dir)
    native_roms_dir = roms_dir / 'native'  # Define path for the native subdirectory
    
    # Set the source path relative to the script directory (to prevent relative path errors)
    source_dir = Path(sys.path[0]) / '..' / 'roms' / 'native'
    
    # 1. Create both the parent roms directory and the native subdirectory
    try:
        roms_dir.mkdir(mode=0o755, parents=True, exist_ok=True) 
        native_roms_dir.mkdir(mode=0o755, parents=True, exist_ok=True)
    except Exception as e:
        raise RuntimeError(f'Failed to create roms directories with proper permissions: {e}')

    # 2. Copy contents using rsync (append '/' to copy directory contents only)
    ret = os.system(f'rsync -av --no-D --no-o --no-g {source_dir}/ {native_roms_dir}/')
    if (ret >> 8) > 0:
        raise RuntimeError(f'Failed rsyncing the roms directory. Exit code: {ret >> 8}')
    

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Install native "emulator"')
    parser.add_argument('--cfg-file',
                        dest='cfg_file',
                        action='store',
                        type=str,
                        default='/etc/emulationstation/es_systems.cfg',
                        help='cfg file to process')
    parser.add_argument('--roms-dir',
                        dest='roms_dir',
                        action='store',
                        type=str,
                        default=None,
                        help='Where the roms are stored')
    parser.add_argument('--theme-source-dir',
                        dest='theme_source_dir',
                        action='store',
                        type=str,
                        default='../themes/native',
                        help='Where is the theme')
    parser.add_argument('--theme-dest-dir',
                        dest='theme_dest_dir',
                        action='store',
                        type=str,
                        default='/etc/emulationstation/themes/es-theme-nes-box/native',
                        help='Where should the theme be stored')
    parser.add_argument('--override',
                        dest='override',
                        action='store_true',
                        help='Override already existing theme')
    parser.add_argument('--no-reboot',
                        dest='no_reboot',
                        action='store_true',
                        help='Don\'t reboot when done')
    args = parser.parse_args()

    # --- Run the installation process ---
    try:
        roms_dir = args.roms_dir
        cfg_file = args.cfg_file
        theme_source_dir = args.theme_source_dir
        theme_dest_dir = args.theme_dest_dir
        override = args.override

        if roms_dir is None:
            roms_dir = find_roms_dir()
            print(f'Found ROMs directory: {roms_dir}')

        create_roms_directory(roms_dir)
        print(f'Successfully created and populated native ROMs directory: {Path(roms_dir) / "native"}')

        if insert_native_system(cfg_file, roms_dir=roms_dir):
            print(f'Successfully modified {cfg_file}')

        copy_theme(theme_source_dir=theme_source_dir,
                   theme_dest_dir=theme_dest_dir,
                   override=override)
        print(f'Successfully copied theme to: {theme_dest_dir}')

        if not args.no_reboot:
            print('Installation complete. Rebooting system...')
            os.system('sudo reboot')
        else:
            print('Installation complete. System reboot skipped (--no-reboot).')

    except RuntimeError as e:
        print(f"ERROR during installation: {e}", file=sys.stderr)
        sys.exit(1)
    except FileNotFoundError as e:
        print(f"FILE ERROR: {e}", file=sys.stderr)
        sys.exit(1)
