#!/usr/bin/python3
import os
import subprocess
import sys

from py_ini_config_modules.common_functions import *
from py_ini_config_modules.system_functions import write_config_to_file, get_comment_symbol

version = '2.12'

argv = sys.argv

commands = (
    'comment',
    'del',
    'get',
    'is_set',
    'set',
    'add',
    'uncomment',
    'del_section',
    'get_commented',
    'is_empty',
    'rename',
    'check',
    '-V',
    '--version',
    '-h',
    '--help'
)

correct_flags = (
    '-n',
    '--no-section',
    '-c',
    '--create',
    '-s',
    '--no-indent',
    '-S',
    '-f',
    '--flush'
)

correct_flags_to_be_removed = (
    '-a',
    '--all',
    '-e',
    '--semicolon-comment',
    '--view-comments',
    '-i',
    '--sort-collected',
    '-v',
    '--verbose',
    '--shadowing',
    '--ignore-empty-values',
    '--ignore-file',
    '--get-filename'
)

if '-V' in argv or '--version' in argv:
    print(f'py-ini-config version {version}')
    sys.exit(0)

if '-h' in argv or '--help' in argv:
    os.environ['PAGER'] = ''
    subprocess.run(['man', 'py-ini-config'])
    sys.exit(0)

separator = '='
if '-s' in argv:
    key_index = argv.index('-s')
    if key_index != len(argv) - 1:
        separator = argv[key_index + 1]
        argv = argv[:key_index] + argv[key_index + 2:]
    else:
        argv = argv[:key_index] + argv[key_index + 1:]

values_separator = ','
if '-S' in argv:
    sindex = argv.index('-S')
    if sindex == len(argv) - 1:
        print('Необходимо указать разделитель для значений параметра')
        sys.exit()
    values_separator = argv[sindex + 1]
    argv = argv[:sindex] + argv[sindex + 2:]

files_to_recursive_scan = []
if '--all' in argv or '-a' in argv:
    if 'get' not in argv and 'is_set' not in argv:
        print('Флаг -a, --all можно использовать только с командами get или is_set')
        sys.exit(0)
    for i in range(len(argv)):
        if argv[i] == '--all':
            argv[i] = '-a'
while '-a' in argv:
    aindex = argv.index('-a')
    if aindex != len(argv) - 1:
        files_to_recursive_scan.append(argv[aindex + 1])
        argv = argv[:aindex] + argv[aindex + 2:]
    else:
        argv.remove('-a')

required_extension = None
if '-e' in argv:
    eindex = argv.index('-e')
    if eindex == len(argv) - 1:
        print('Необходимо указать требуемое расширение')
        sys.exit(0)
    required_extension = argv[eindex + 1]
    argv = argv[:eindex] + argv[eindex + 2:]

noindent = False
if '--no-indent' in argv:
    noindent = True
    argv.remove('--no-indent')

com_symbol = '#'
if '--semicolon-comment' in argv:
    com_symbol = ';'
    argv.remove('--semicolon-comment')

view_comments = False
if '--view-comments' in argv:
    view_comments = True
    argv.remove('--view-comments')

flush = False
if '-f' in argv:
    argv.remove('-f')
    flush = True
elif '--flush' in argv:
    argv.remove('--flush')
    flush = True

inversed_order = False
if '-i' in argv:
    argv.remove('-i')
    inversed_order = True

sort_collected = False
if '--sort-collected' in argv:
    argv.remove('--sort-collected')
    sort_collected = True

verbose = False
if '-v' in argv or '--verbose' in argv:
    if '-v' in argv:
        argv.remove('-v')
    else:
        argv.remove('--verbose')
    verbose = True

shadowing = False
if '--shadowing' in argv:
    argv.remove('--shadowing')
    shadowing = True

ignore_empty_values=False
if '--ignore-empty-values' in argv:
    argv.remove('--ignore-empty-values')
    ignore_empty_values = True

get_filename=False
if '--get-filename' in argv:
    if 'get' not in argv:
        print('Флаг --get-filename можно использовать только с командой get')
        sys.exit(0)
    argv.remove('--get-filename')
    get_filename = True

ignore_files = []
while '--ignore-file' in argv:
    if 'get' not in argv and 'is_set' not in argv:
        print('Флаг -a, --all можно использовать только с командами get или is_set')
        sys.exit(0)

    ignore_index = argv.index('--ignore-file')
    if ignore_index != len(argv) - 1:
        ignore_files.append(argv[ignore_index + 1])
        argv = argv[:ignore_index] + argv[ignore_index + 2:]
    else:
        argv.remove('--ignore-file')

# non_existing_flags = [i for i in argv if i.startswith('-') and i not in correct_flags]
# while non_existing_flags:
#     flag = non_existing_flags.pop()
#     if verbose:
#         eprint(f'Флаг {flag} не поддерживается данной программой')
#     argv.remove(flag)

# Creating config file
if ('--create' in argv or '-c' in argv) and len(argv) >= 4 and os.path.isfile(argv[3]):
    print(f'Внимание: файл {argv[3]} существует. Флаг --create будет проигнорирован.')
    if '--create' in argv:
        argv.remove('--create')
    else:
        argv.remove('-c')

if '--create' in argv or '-c' in argv:
    if 'set' not in argv and 'add' not in argv:
        eprint('Ошибка - создание файла возможно только с опцией set или add.')
        sys.exit(1)
    if '--create' in argv:
        indx = argv.index('--create')
    else:
        indx = argv.index('-c')
    if indx == len(argv) - 1:
        eprint('Ошибка - вы не указали имя файла для создания.')
        sys.exit(1)
    filename = argv[indx + 1]
    subprocess.run(f'touch {filename}', shell=True)
    argv = argv[:indx] + argv[indx + 2:]
    if len(argv) < 5:
        print('Для установления или добавления значения переменной в новом файле должно не менее 4 параметров '
              'командной строки.')
        print('Синтаксис: py-ini-config set | add [-c, --create] filename [section, -n, --no-section]'
              ' var value [-s separator] [--no-indent]')
        sys.exit()
    if '-n' in argv or '--no-section' in argv:
        if '-n' in argv:
            argv.remove('-n')
        else:
            argv.remove('--no-section')
        config = ini_config_set(
            file=filename,
            var=argv[2],
            value=argv[3],
            noindent=noindent,
            com_symbol=com_symbol,
            view_comments=view_comments,
            separator=separator,
            use_section=False
        )
    else:
        config = ini_config_set(
            file=filename,
            section=argv[2],
            var=argv[3],
            value=argv[4],
            noindent=noindent,
            com_symbol=com_symbol,
            view_comments=view_comments,
            separator=separator
        )
    write_config_to_file(config, filename)

# Working with config files with no sections
elif '-n' in argv or '--no-section' in argv:
    if '-n' in argv:
        argv.remove('-n')
    else:
        argv.remove('--no-section')

    if len(argv) < 3:
        eprint('Ошибка - недостаточно команд.')
        sys.exit(1)
    elif argv[1] not in commands:
        eprint('Ошибка - неизвестная команда.')
        sys.exit(1)
    elif not os.path.isfile(argv[2]) and not files_to_recursive_scan:
        eprint('Ошибка - указанный файл не существует.')
        sys.exit(1)
    else:
        if com_symbol == '#' and not files_to_recursive_scan:
            com_symbol = get_comment_symbol(argv[2])
        if argv[1] == 'set':
            if len(argv) != 5:
                print(
                    'Для установления значения переменной вне секции должно быть не менее 5 параметров командной '
                    'строки.')
                print('Синтаксис: py-ini-config set file [-n, --no-section] var value [-s separator]')
                sys.exit()
            config = ini_config_set(
                file=argv[2],
                var=argv[3],
                value=argv[4],
                noindent=noindent,
                com_symbol=com_symbol,
                view_comments=view_comments,
                separator=separator,
                use_section=False
            )
            write_config_to_file(config=config, file=argv[2])

        elif argv[1] == 'comment':
            if len(argv) != 4:
                print('Для комментирования переменной вне секции должно быть не менее 4 параметров командной строки.')
                print('Синтаксис: py-ini-config comment file [-n, --no-section] var [-s separator]')
                sys.exit()
            else:
                config = ini_config_comment(
                    file=argv[2],
                    var=argv[3],
                    com_symbol=com_symbol,
                    separator=separator,
                    use_section=False
                )
            if config is not False:
                write_config_to_file(config=config, file=argv[2])
            else:
                sys.exit(1)

        elif argv[1] == 'del':
            if len(argv) < 4:
                print('Для удаления переменной или её значения вне секции должно быть не менее 4 параметров командной '
                      'строки.')
                print('Синтаксис: py-ini-config del file [-n, --no-section] var [value] [-s separator] [-S '
                      'values_separator]')
                sys.exit()
            if len(argv) > 4:
                value = argv[4]
            else:
                value = None
            config = ini_config_del(
                file=argv[2],
                var=argv[3],
                com_symbol=com_symbol,
                separator=separator,
                values_separator=values_separator,
                value=value,
                use_section=False
            )
            if config is not False:
                write_config_to_file(config=config, file=argv[2])
            else:
                sys.exit(1)

        elif argv[1] == 'get':
            if len(argv) != 4 and not files_to_recursive_scan:
                print(
                    'Для получения значения переменной вне секции должно быть не менее 4 параметров командной строки.')
                print('Синтаксис: py-ini-config get file [-n, --no-section] var [-s separator]')
                sys.exit()
            if files_to_recursive_scan:
                res = ini_config_get_recursive(
                    var=argv[2],
                    separator=separator,
                    inversed_order=inversed_order,
                    files_to_recursive_scan=files_to_recursive_scan,
                    required_extension=required_extension,
                    sort_collected=sort_collected,
                    shadowing=shadowing,
                    verbose=verbose,
                    use_section=False,
                    ignore_empty_values=ignore_empty_values,
                    ignore_files=ignore_files,
                    get_filename=get_filename
                )
                if res or (res == '' and not ignore_empty_values):
                    print(res)
                else:
                    sys.exit(1)
            else:
                res = ini_config_get(
                    file=argv[2],
                    var=argv[3],
                    separator=separator,
                    use_section=False
                )
                if res:
                    print(res)
                else:
                    sys.exit(1)

        elif argv[1] == 'is_set':
            if len(argv) < 4 and not files_to_recursive_scan:
                print('Для определения существования значения переменной вне секции должно быть не меньше 4 параметров '
                      'командной строки.')
                print('Синтаксис: py-ini-config is_set file [-n , --no-section] var [value] [-s separator]')
                sys.exit()
            if files_to_recursive_scan:
                sys.exit(ini_config_get_recursive(
                    var=argv[2],
                    value=argv[3] if len(argv) >= 4 else None,
                    separator=separator,
                    values_separator=values_separator,
                    files_to_recursive_scan=files_to_recursive_scan,
                    shadowing=shadowing,
                    required_extension=required_extension,
                    sort_collected=sort_collected,
                    verbose=verbose,
                    is_set=True,
                    use_section=False,
                    ignore_empty_values=ignore_empty_values,
                    ignore_files=ignore_files,
                    get_filename=get_filename
                ))
            if len(argv) == 4:
                value = None
            else:
                value = argv[4]
            sys.exit(ini_config_get(
                file=argv[2],
                var=argv[3],
                value=value,
                separator=separator,
                values_separator=values_separator,
                is_set=True,
                use_section=False
            ))

        elif argv[1] == 'uncomment':
            if len(argv) != 4:
                print('Для снятия комментария с переменной вне секции должно быть не менее 4 параметров '
                      'командной строки.')
                print('Синтаксис: py-ini-config uncomment file [-n , --no-section] var [-s separator]')
                sys.exit()
            else:
                config = ini_config_comment(
                    file=argv[2],
                    var=argv[3],
                    com_symbol=com_symbol,
                    separator=separator,
                    uncomment=True,
                    use_section=False
                )
            if config is not False:
                write_config_to_file(config=config, file=argv[2])
            else:
                sys.exit(1)

        elif argv[1] == 'get_commented':
            if len(argv) != 4:
                print('Для получения значения закомментированной переменной вне секции должно быть не менее 4 '
                      'параметров командной строки.')
                print('Синтаксис: py-ini-config get_commented file [-n, --no-section] var [-s separator]')
                sys.exit()
            res = ini_config_get(
                file=argv[2],
                var=argv[3],
                com_symbol=com_symbol,
                separator=separator,
                get_commented=True,
                use_section=False
            )
            if res:
                print(*res, sep='\n')
            else:
                sys.exit(1)

        elif argv[1] == 'add':
            if len(argv) != 5:
                print('Для добавления значения переменной вне секции должно быть не менее 5 '
                      'параметров командной строки.')
                print('Синтаксис: py-ini-config add file [-n, --no-section] var value [-s separator] [-S '
                      'values_separator]')
                sys.exit()
            config = ini_config_set(
                file=argv[2],
                var=argv[3],
                value=argv[4],
                noindent=noindent,
                com_symbol=com_symbol,
                view_comments=view_comments,
                separator=separator,
                values_separator=values_separator,
                add=True,
                use_section=False
            )
            if config:
                write_config_to_file(config=config, file=argv[2])
            else:
                sys.exit(1)

        elif argv[1] == 'rename':
            if len(argv) != 5:
                print('Для переименования переменной вне секции должно быть не менее 5 '
                      'параметров командной строки.')
                print('Синтаксис: py-ini-config rename file [-n, --no-section] var new_name [-s separator] [-S '
                      'values_separator]')
                sys.exit()
            config = ini_config_rename(
                file=argv[2],
                var=argv[3],
                new_name=argv[4],
                separator=separator,
                use_section=False
            )
            if config:
                write_config_to_file(config=config, file=argv[2])
            else:
                sys.exit(1)
        elif argv[1] == 'check':
            if len(argv) != 3:
                print('Для проверки файла конфига необходимо ровно 4 параметра командной строки.\n'
                      'Синтаксис: py-ini-config check file -n')
                sys.exit()
            sys.exit(
                ini_config_check(
                    file=argv[2],
                    separator=separator,
                    com_symbol=com_symbol,
                    use_section=False
                )
            )

elif len(argv) > 1 and argv[1] not in commands:
    eprint('Ошибка - неизвестная команда.')
    sys.exit(1)
elif len(argv) < 4 and argv[1] != 'check':
    eprint('Ошибка - недостаточно параметров.')
    sys.exit(1)
elif not os.path.isfile(argv[2]) and not files_to_recursive_scan:
    eprint('Ошибка - указанный файл не существует.')
    sys.exit(1)
else:
    if com_symbol == '#' and not files_to_recursive_scan:
        com_symbol = get_comment_symbol(argv[2])
    if argv[1] == 'set':
        if len(argv) != 6:
            print('Для установления значения переменной в секции должно быть не менее 5 параметров командной строки.')
            print('Синтаксис: py-ini-config set file section var value [-s separator]')
            sys.exit()
        config = ini_config_set(
            file=argv[2],
            section=argv[3],
            var=argv[4],
            value=argv[5],
            noindent=noindent,
            com_symbol=com_symbol,
            view_comments=view_comments,
            separator=separator
        )
        write_config_to_file(config=config, file=argv[2])

    elif argv[1] == 'comment':
        if len(argv) < 4:
            print('Для комментирования переменной в секции должно быть не менее 3 параметров командной строки.')
            print('Синтаксис: py-ini-config comment file section [var] [-s separator]')
            sys.exit()
        # Указана переменная
        if len(argv) == 5:
            config = ini_config_comment(
                file=argv[2],
                section=argv[3],
                com_symbol=com_symbol,
                var=argv[4],
                separator=separator
            )
        else:
            config = ini_config_comment(
                file=argv[2],
                section=argv[3],
                com_symbol=com_symbol,
                separator=separator
            )
        if config is not False:
            write_config_to_file(config=config, file=argv[2])
        else:
            sys.exit(1)

    elif argv[1] == 'del':
        if len(argv) < 5:
            print('Для удаления переменной или её значения в секции должно быть не менее 4 '
                  'параметров командной строки.')
            print('Синтаксис: py-ini-config del file section var [value] [-f, --flush] [-s separator] '
                  '[-S values_separator]')
            sys.exit()

        if len(argv) > 5:
            value = argv[5]
        else:
            value = None
        config = ini_config_del(
            file=argv[2],
            section=argv[3],
            var=argv[4],
            flush=flush,
            com_symbol=com_symbol,
            separator=separator,
            value=value,
            values_separator=values_separator
        )
        if config is not False:
            write_config_to_file(config=config, file=argv[2])
        else:
            sys.exit(1)

    elif argv[1] == 'get':
        if len(argv) < 4 and not files_to_recursive_scan:
            print('Для получения значения переменной в секции должно быть не менее 3 параметров командной строки.')
            print('Синтаксис: py-ini-config get file section [var] [-s separator]')
            sys.exit()
        if files_to_recursive_scan:
            res = ini_config_get_recursive(
                section=argv[2],
                var=argv[3],
                separator=separator,
                inversed_order=inversed_order,
                files_to_recursive_scan=files_to_recursive_scan,
                required_extension=required_extension,
                sort_collected=sort_collected,
                shadowing=shadowing,
                verbose=verbose,
                ignore_empty_values=ignore_empty_values,
                ignore_files=ignore_files,
                get_filename=get_filename
            )
        else:
            if len(argv) == 4:
                var = None
            else:
                var = argv[4]
            res = ini_config_get(
                file=argv[2],
                section=argv[3],
                var=var,
                separator=separator
            )
        if res:
            print(res)
        else:
            sys.exit(1)

    elif argv[1] == 'is_set':
        if len(argv) < 4 and not files_to_recursive_scan:
            print(
                'Для определения существования переменной в секции должно быть от 4 до 6 параметров командной строки.')
            print('Синтаксис: py-ini-config is_set file section [var] [value] [-s separator]')
            sys.exit()
        if files_to_recursive_scan:
            sys.exit(ini_config_get_recursive(
                section=argv[2],
                var=argv[3],
                value=argv[4] if len(argv) >= 5 else None,
                separator=separator,
                values_separator=values_separator,
                files_to_recursive_scan=files_to_recursive_scan,
                shadowing=shadowing,
                sort_collected=sort_collected,
                verbose=verbose,
                required_extension=required_extension,
                is_set=True,
                ignore_empty_values=ignore_empty_values,
                ignore_files=ignore_files,
                get_filename=get_filename
            ))
        if len(argv) < 5:
            var = None
        else:
            var = argv[4]
        if len(argv) < 6:
            value = None
        else:
            value = argv[5]
        sys.exit(ini_config_get(
            file=argv[2],
            section=argv[3],
            var=var,
            value=value,
            separator=separator,
            values_separator=values_separator,
            is_set=True
        ))

    elif argv[1] == 'uncomment':
        if len(argv) < 4:
            print('Для снятия комментирования переменной в секции должно быть не менее 3 параметров командной строки.')
            print('Синтаксис: py-ini-config uncomment file section [var] [-s separator]')
            sys.exit()
        if len(argv) == 4:
            var = None
        else:
            var = argv[4]

        config = ini_config_comment(
            file=argv[2],
            section=argv[3],
            com_symbol=com_symbol,
            var=var,
            separator=separator,
            uncomment=True
        )

        if config is not False:
            write_config_to_file(config=config, file=argv[2])
        else:
            sys.exit(1)

    elif argv[1] == 'del_section':
        if len(argv) != 4:
            print('Для удаления секции должно быть не менее 3 параметров командной строки.')
            print('Синтаксис: py-ini-config del_section file section [-s separator]')
            sys.exit()
        config = ini_config_del(
            file=argv[2],
            section=argv[3],
            separator=separator,
            del_section=True
        )
        if config is not False:
            write_config_to_file(config=config, file=argv[2])
        else:
            sys.exit(1)

    elif argv[1] == 'get_commented':
        if len(argv) != 5:
            print(
                'Для получения значения закомментированной переменной в секции должно быть не менее 4 параметров '
                'командной строки.')
            print('Синтаксис: py-ini-config get_commented file section var [-s separator]')
            sys.exit()
        res = ini_config_get(
            file=argv[2],
            section=argv[3],
            var=argv[4],
            com_symbol=com_symbol,
            separator=separator,
            values_separator=values_separator,
            get_commented=True
        )
        if res:
            print(*res, sep='\n')
        else:
            sys.exit(1)

    elif argv[1] == 'is_empty':
        if len(argv) != 4:
            print('Для определения наличия переменных в секции должно быть не менее 3 параметров командной строки.')
            print('Синтаксис: py-ini-config is_empty file section [-s separator]')
            sys.exit()
        sys.exit(ini_config_is_empty(
            file=argv[2],
            section=argv[3],
            separator=separator
        ))

    elif argv[1] == 'add':
        if len(argv) != 6:
            print('Для добавления значения переменной в секции должно быть не менее 5 параметров командной строки.')
            print('Синтаксис: py-ini-config add file section var value [-s separator] [-S values_separator]')
            sys.exit()

        config = ini_config_set(
            file=argv[2],
            section=argv[3],
            var=argv[4],
            value=argv[5],
            noindent=noindent,
            com_symbol=com_symbol,
            view_comments=view_comments,
            separator=separator,
            values_separator=values_separator,
            add=True
        )
        write_config_to_file(config=config, file=argv[2])

    elif argv[1] == 'rename':
        if len(argv) != 6:
            print('Для переименования переменной в секции должно быть не менее 5 параметров командной строки.')
            print('Синтаксис: py-ini-config rename file section var new_name [-s separator]')
            sys.exit()
        config = ini_config_rename(
            file=argv[2],
            section=argv[3],
            var=argv[4],
            new_name=argv[5],
            separator=separator,
            use_section=True
        )
        if config:
            write_config_to_file(config=config, file=argv[2])
        else:
            sys.exit(1)
    elif argv[1] == 'check':
        if len(argv) != 3:
            print('Для проверки файла конфига необходимо ровно 3 параметра командной строки.\n'
                  'Синтаксис: py-ini-config check file')
            sys.exit()
        sys.exit(
            ini_config_check(
                file=argv[2],
                separator=separator,
                com_symbol=com_symbol,
                use_section=True
            )
        )
