import sys
sys.dont_write_bytecode = True
import os
from PyQt5.QtWidgets import QApplication
import RPi.GPIO as gpio
from array import *
import time
import subprocess
import signal
import hashlib
import json

from threading import Lock
from video_player import client_play_video, find_file, get_length, get_timeout, \
    set_Flag_LoopingVideoPlayer, video, remove_createdVideos 
from stepper_controller import Thread, autotest, return_start, stepperJustGo, steppermovement, initialize_gpio_pins, get_thisstep, set_Flag_JustGo, get_Flag_JustGo
from led_controller import GREEN, YELLOW, waitingmode_start, waitingmode_fin, LEDRGB
from client_handler import get_message_play_video, get_setting_client, new_socket, setting_server, \
    onClient, request_above, \
    client_request, setting_request, join_thread, \
    filepath_setting_request, \
    get_filepath_settinh_client

lock = Lock()

# autotest_filaname = "VDNHzastavka.mp4"
# autotest_filaname = "waf.mp4"


def calculate_hash(directory):
    hash_md5 = hashlib.md5()
    ignore_extensions = ('.log', '.tmp', '.pyc', '.swp')  # Расширяем список игнорируемых файлов
    ignore_files = ('package.json',)  # Игнорируем файл package.json
    all_files = []

    for root, dirs, files in os.walk(directory):
        for file in files:
            if not file.endswith(ignore_extensions) and file not in ignore_files:
                file_path = os.path.join(root, file)
                all_files.append(file_path)

    all_files.sort()  # Гарантируем одинаковый порядок файлов

    for file_path in all_files:
        with open(file_path, "rb") as f:
            for chunk in iter(lambda: f.read(4096), b""):
                hash_md5.update(chunk)
        print(f"Processed: {file_path}")  # Логируем обработанные файлы

    return hash_md5.hexdigest()

def update_package_json():
    project_directory = '/home/blade/Documents/neuro-fluger/controllers-101'
    project_hash = calculate_hash(project_directory)
    package_data = {
        "name": "neuro-fluger",
        "description": "Сервер лопасти нейрофлюгера",
        "version": "1.0.0",
        "main": "main.py",
        "authors": "Игорь Сорока, Владислав Голев, ООО НЕЙРО-СИТИ",
        "license": "MIT",
        "hash": project_hash
    }
    with open(os.path.join(project_directory, 'package.json'), 'w', encoding='utf-8') as json_file:
        json.dump(package_data, json_file, indent=4, ensure_ascii=False)
        
def handle_navigation_null():
    global client_socket, reqType, deg, namefile, screenplay, R, G, B, R2, G2, B2, necessarystep, setting, thisstep, \
        autotest_client, flage_remove_cV, counter_client_play_video, counter_setting_request, \
        DIR, STEP, ENA, DEGSTEP, CW, CCW, MICROSTEP, FACTOR, MAX_SPEED_DELAY_small_dist, START_DELAY_small_dist, \
        FIN_DELAY_small_dist, MAX_SPEED_DELAY_long_dist, START_DELAY_long_dist, FIN_DELAY_long_dist, HALL, board_PIXEL, \
        number_LED, brightness, line_script_Wait, R_wait, G_wait, B_wait, R2_wait, G2_wait, B2_wait, initXaxis, \
        initYaxis, sizeXaxis, sizeYaxis, pixel, SPR, SYSCOF, filepath_settinh_client, filepath, setting_client

    if thisstep == 0:
        print('Зашли в navig_null and thisstep=0')
        print(f"Запрос клиента выполнен: {setting_request()}")
        setting_client = get_setting_client()
        print(f"Очередь команд: {setting_client}")
        onClient("Запрос клиента выполнен", client_socket)
        time.sleep(.1)
        filepath_settinh_client = get_filepath_settinh_client()
        if filepath_settinh_client:
            filepath_settinh_client.pop(0)     
            setting_client = get_setting_client()
        if setting_client:
            setting_client.pop(0)
                
        if filepath_settinh_client and filepath_settinh_client[0]:
            while filepath_settinh_client and filepath_settinh_client[0] == "0":
                print(f'Вывод массива с видео перед исключением из него нулей: {filepath_settinh_client}')
                setting_client = get_setting_client()
                if setting_client:
                    setting_client.pop(0)
                filepath_settinh_client = get_filepath_settinh_client()
                if filepath_settinh_client:
                    filepath_settinh_client.pop(0)          
            print('Массив с названиями видео очищен от нулей.')

        join_thread()
        return True
    else:
        print('Зашли в navig_null in ELSE')
        time.sleep(.1)
        try:
            if request_above(False):
                return True
        except Exception as e:
            print("Error:", str(e))

        setting_client = get_setting_client()
        print(f"Очередь команд: {setting_client}")
        # Видеозаглушка и возвращение к начальной точке
        set_Flag_LoopingVideoPlayer(False)
        navigation_filename = "russpas_zastavka.mp4"
        thread_loopVideo = Thread(target=video, args=(find_file(navigation_filename), get_length(find_file(navigation_filename)), initXaxis, initYaxis, sizeXaxis, sizeYaxis, True))
        thread_loopVideo.start()
        set_Flag_LoopingVideoPlayer(return_start())
        thread_loopVideo.join()
        set_Flag_LoopingVideoPlayer(True)
        print(f"Запрос клиента выполнен: {setting}")
        onClient("Запрос клиента выполнен", client_socket)
        filepath_settinh_client = get_filepath_settinh_client()
        if filepath_settinh_client:
            filepath_settinh_client.pop(0)     
        setting_client = get_setting_client()
        if setting_client:
            setting_client.pop(0)
                
        print(f'Вывод массива с видео перед исключением из него нулей: {filepath_settinh_client}')
        if filepath_settinh_client and filepath_settinh_client[0]:
            while filepath_settinh_client and filepath_settinh_client[0] == "0":
                print(f'Вывод массива с видео перед исключением из него нулей: {filepath_settinh_client}')
                setting_client = get_setting_client()
                if setting_client:
                    setting_client.pop(0)
                filepath_settinh_client = get_filepath_settinh_client()
                if filepath_settinh_client:
                    filepath_settinh_client.pop(0)
            print('Массив с названиями видео очищен от нулей.')
        join_thread()
        return True    


def handle_performance():
    global client_socket, reqType, deg, namefile, screenplay, R, G, B, R2, G2, B2, necessarystep, setting, thisstep, \
        autotest_client, flage_remove_cV, counter_client_play_video, counter_setting_request, \
        DIR, STEP, ENA, DEGSTEP, CW, CCW, MICROSTEP, FACTOR, MAX_SPEED_DELAY_small_dist, START_DELAY_small_dist, \
        FIN_DELAY_small_dist, MAX_SPEED_DELAY_long_dist, START_DELAY_long_dist, FIN_DELAY_long_dist, HALL, board_PIXEL, \
        number_LED, brightness, line_script_Wait, R_wait, G_wait, B_wait, R2_wait, G2_wait, B2_wait, initXaxis, \
        initYaxis, sizeXaxis, sizeYaxis, pixel, SPR, SYSCOF, filepath_settinh_client, filepath, setting_client

    print('Запущен performance')
    join_thread()  # Завершение всех текущих потоков перед запуском новых операций

    filepath = filepath_setting_request()
    print("Ждем команду для воспроизведения видео")
    message_play_video = get_message_play_video()
    setting_client = get_setting_client()
    filepath_settinh_client = get_filepath_settinh_client()
    # Если видео не сыграло
    if not(client_play_video(filepath, True, counter_client_play_video, filepath_settinh_client, message_play_video, setting)):
        # То очищаем очередь комманд
        setting_client = get_setting_client()
        if setting_client:
            setting_client.pop(0)
        filepath_settinh_client = get_filepath_settinh_client()
        if filepath_settinh_client:
            filepath_settinh_client.pop(0)
        # Возвращаем лопасть в нулевую точку
        # Заглушка
        set_Flag_LoopingVideoPlayer(False)
        navigation_filename = "russpas_zastavka.mp4"
        thread_loopVideo = Thread(target=video, args=(find_file(navigation_filename), get_length(find_file(navigation_filename)), initXaxis, initYaxis, sizeXaxis, sizeYaxis, True))
        thread_loopVideo.start()
        set_Flag_LoopingVideoPlayer(return_start())
        thread_loopVideo.join()
        set_Flag_LoopingVideoPlayer(True)
        #
        print(f"Запрос клиента выполнен: {setting}")
        onClient("Запрос клиента выполнен")
        
        # И перезапускаем цикл
        return True
    
    waitingmode_fin(R_wait, B_wait, G_wait, R2_wait, B2_wait, G2_wait)

    try:
        if request_above(False):
            return True
    except Exception as e:
        print("Error:", str(e))
    
    flag_onClient = True
    # gpio.output(ENA, gpio.LOW)
    time.sleep(.1)
    thisstep = get_thisstep()

    thread_LEDRGB = Thread(target=LEDRGB, args=(number_LED, R, B, G, R2, B2, G2, screenplay))
    thread_LEDRGB.start()
    thread_steppermovement = Thread(target=steppermovement, args=(necessarystep, flag_onClient, thisstep))
    thread_steppermovement.start()

    if filepath is not None:
        timeout = get_timeout()
        video(filepath, timeout, initXaxis, initYaxis, sizeXaxis, sizeYaxis)
    else:
        print('Отсутствует видеофайл для воспроизведения. Не запускаем видеоплеер')

    thread_steppermovement.join()
    time.sleep(.1)
    # gpio.output(ENA, gpio.HIGH)
    thread_LEDRGB.join(0.1)
    waitingmode_start(R_wait, B_wait, G_wait, R2_wait, B2_wait, G2_wait)

    return False

def handle_other_cases():
    global client_socket, reqType, deg, namefile, screenplay, R, G, B, R2, G2, B2, necessarystep, setting, thisstep, \
        autotest_client, flage_remove_cV, counter_client_play_video, counter_setting_request, \
        DIR, STEP, ENA, DEGSTEP, CW, CCW, MICROSTEP, FACTOR, MAX_SPEED_DELAY_small_dist, START_DELAY_small_dist, \
        FIN_DELAY_small_dist, MAX_SPEED_DELAY_long_dist, START_DELAY_long_dist, FIN_DELAY_long_dist, HALL, board_PIXEL, \
        number_LED, brightness, line_script_Wait, R_wait, G_wait, B_wait, R2_wait, G2_wait, B2_wait, initXaxis, \
        initYaxis, sizeXaxis, sizeYaxis, pixel, SPR, SYSCOF, filepath_settinh_client, filepath, setting_client


    print('Не запущен performance')
    # if reqType == "navigation":
    #     autotest_filename = ""
    # else:
    #     autotest_filename = "waf.mp4"

    flag_onClient = True
    # gpio.output(ENA, gpio.LOW)
    time.sleep(.1)

    set_Flag_LoopingVideoPlayer(False)
    
    # Выбор видеозаглушки
    if reqType == 'navigation':
        navigation_filename = "navigation__zastavka.mp4"
    else:
        navigation_filename = "VDNH_zastavka.mp4"
    
    thread_loopVideo = Thread(target=video, args=(find_file(navigation_filename), get_length(find_file(navigation_filename)), initXaxis, initYaxis, sizeXaxis, sizeYaxis, True))
    thread_loopVideo.start()
    timeout = get_timeout()

    time.sleep(.1)
    # gpio.output(ENA, gpio.HIGH)

    thisstep = get_thisstep()
    set_Flag_LoopingVideoPlayer(steppermovement(necessarystep, flag_onClient, thisstep))

    join_thread()
    thread_loopVideo.join()
    set_Flag_LoopingVideoPlayer(True)

    try:
        if request_above(False):
            return True
    except Exception as e:
        print("Error:", str(e))


    filepath_settinh_client = get_filepath_settinh_client()
    filepath = filepath_setting_request()

    print("Ждем команду для воспроизведения видео")

    message_play_video = get_message_play_video()
    try:
        # Если видео не сыграло
        if not(client_play_video(filepath, True, counter_client_play_video, filepath_settinh_client, message_play_video, setting)):
            # То очищаем очередь комманд
            setting_client = get_setting_client()
            if setting_client:
                setting_client.pop(0)
            filepath_settinh_client = get_filepath_settinh_client()
            if filepath_settinh_client:
                filepath_settinh_client.pop(0)

            # Возвращаем лопасть в нулевую точку
            # Заглушка
            set_Flag_LoopingVideoPlayer(False)
            navigation_filename = "russpas_zastavka.mp4"
            thread_loopVideo = Thread(target=video, args=(find_file(navigation_filename), get_length(find_file(navigation_filename)), initXaxis, initYaxis, sizeXaxis, sizeYaxis, True))
            thread_loopVideo.start()
            set_Flag_LoopingVideoPlayer(return_start())
            thread_loopVideo.join()
            set_Flag_LoopingVideoPlayer(True)
            #
            
            print(f"Запрос клиента выполнен: {setting}")
            onClient("Запрос клиента выполнен")
            # И перезапускаем цикл
            return True
    except Exception as e:
        print("Error:", str(e))

    time.sleep(.1)
    waitingmode_fin(R_wait, B_wait, G_wait, R2_wait, B2_wait, G2_wait)

    thread_LEDRGB = Thread(target=LEDRGB, args=(number_LED, R, B, G, R2, B2, G2, screenplay))
    thread_LEDRGB.start()
    if filepath is not None:
        timeout = get_timeout()
        video(filepath, timeout, initXaxis, initYaxis, sizeXaxis, sizeYaxis, False)
    else:
        print('Отсутствует видеофайл для воспроизведения. Не запускаем видеоплеер')
        setting_client = get_setting_client()
        if setting_client:
            setting_client.pop(0)
        filepath_settinh_client = get_filepath_settinh_client()
        if filepath_settinh_client:
            filepath_settinh_client.pop(0)



    thread_LEDRGB.join(0.1)
    waitingmode_start(R_wait, B_wait, G_wait, R2_wait, B2_wait, G2_wait)
    return False

def handle_representation():
    global client_socket, reqType, deg, namefile, screenplay, R, G, B, R2, G2, B2, necessarystep, setting, thisstep, \
        autotest_client, flage_remove_cV, counter_client_play_video, counter_setting_request, \
        DIR, STEP, ENA, DEGSTEP, CW, CCW, MICROSTEP, FACTOR, MAX_SPEED_DELAY_small_dist, START_DELAY_small_dist, \
        FIN_DELAY_small_dist, MAX_SPEED_DELAY_long_dist, START_DELAY_long_dist, FIN_DELAY_long_dist, HALL, board_PIXEL, \
        number_LED, brightness, line_script_Wait, R_wait, G_wait, B_wait, R2_wait, G2_wait, B2_wait, initXaxis, \
        initYaxis, sizeXaxis, sizeYaxis, pixel, SPR, SYSCOF, filepath_settinh_client, filepath, setting_client


    print('Запущен representation')
    flag_onClient = True
    # gpio.output(ENA, gpio.LOW)
    time.sleep(.1)

    set_Flag_LoopingVideoPlayer(False)
    navigation_filename = "VDNHrusspas_zastavka.mp4"
    thread_loopVideo = Thread(target=video, args=(find_file(navigation_filename), get_length(find_file(navigation_filename)), initXaxis, initYaxis, sizeXaxis, sizeYaxis, True))
    thread_loopVideo.start()
    timeout = get_timeout()

    time.sleep(.1)
    # gpio.output(ENA, gpio.HIGH)

    thisstep = get_thisstep()
    set_Flag_LoopingVideoPlayer(steppermovement(necessarystep, flag_onClient, thisstep))

    join_thread()
    thread_loopVideo.join()
    set_Flag_LoopingVideoPlayer(True)

    try:
        if request_above(False):
            return True
    except Exception as e:
        print("Error:", str(e))

    filepath_settinh_client = get_filepath_settinh_client()
    print("Лопасть готова к презентации")
    filepath = filepath_setting_request()
    message_play_video = get_message_play_video()
    try:
        # Если видео не сыграло
        if not(client_play_video(filepath, True, counter_client_play_video, filepath_settinh_client, message_play_video, setting)):
            # То очищаем очередь комманд
            setting_client = get_setting_client()
            if setting_client:
                setting_client.pop(0)
            filepath_settinh_client = get_filepath_settinh_client()
            if filepath_settinh_client:
                filepath_settinh_client.pop(0)

            # Возвращаем лопасть в нулевую точку
            # Заглушка
            set_Flag_LoopingVideoPlayer(False)
            navigation_filename = "russpas_zastavka.mp4"
            thread_loopVideo = Thread(target=video, args=(find_file(navigation_filename), get_length(find_file(navigation_filename)), initXaxis, initYaxis, sizeXaxis, sizeYaxis, True))
            thread_loopVideo.start()
            set_Flag_LoopingVideoPlayer(return_start())
            thread_loopVideo.join()
            set_Flag_LoopingVideoPlayer(True)
            #
            print(f"Запрос клиента выполнен: {setting}")
            onClient("Запрос клиента выполнен")
            # И перезапускаем цикл
            return True

    except Exception as e:
        print("Error:", str(e))
    time.sleep(.1)

    waitingmode_fin(R_wait, B_wait, G_wait, R2_wait, B2_wait, G2_wait)

    try:
        if request_above(False):
            return True
    except Exception as e:
        print("Error:", str(e))


    thread_LEDRGB = Thread(target=LEDRGB, args=(number_LED, R, B, G, R2, B2, G2, screenplay))
    thread_LEDRGB.start()

    if filepath is not None:
        set_Flag_JustGo(True)
        thread_steppermovement = Thread(target=stepperJustGo, args=())
        thread_steppermovement.start()
        timeout = get_timeout()
        set_Flag_JustGo(video(filepath, timeout, initXaxis, initYaxis, sizeXaxis, sizeYaxis, False))
        # time.sleep(timeout)
        thread_steppermovement.join()
        set_Flag_JustGo(False)
    else:
        print('Отсутствует видеофайл для воспроизведения. Не запускаем видеоплеер')
        setting_client = get_setting_client()
        if setting_client:
            setting_client.pop(0)
        filepath_settinh_client = get_filepath_settinh_client()
        if filepath_settinh_client:
            filepath_settinh_client.pop(0)
        return True    
    thread_LEDRGB.join(0.1)
    waitingmode_start(R_wait, B_wait, G_wait, R2_wait, B2_wait, G2_wait)
    # Возврат лопасти к начальной точке координат после прекращения видео
    set_Flag_LoopingVideoPlayer(False)
    navigation_filename = "VDNH_zastavka.mp4"
    thread_loopVideo = Thread(target=video, args=(find_file(navigation_filename), get_length(find_file(navigation_filename)), initXaxis, initYaxis, sizeXaxis, sizeYaxis, True))
    thread_loopVideo.start()
    set_Flag_LoopingVideoPlayer(return_start())
    thread_loopVideo.join()
    set_Flag_LoopingVideoPlayer(True)

    return False

def main():
    global client_socket, reqType, deg, namefile, screenplay, R, G, B, R2, G2, B2, necessarystep, setting, thisstep, \
        autotest_client, flage_remove_cV, counter_client_play_video, counter_setting_request, \
        DIR, STEP, ENA, DEGSTEP, CW, CCW, MICROSTEP, FACTOR, MAX_SPEED_DELAY_small_dist, START_DELAY_small_dist, \
        FIN_DELAY_small_dist, MAX_SPEED_DELAY_long_dist, START_DELAY_long_dist, FIN_DELAY_long_dist, HALL, board_PIXEL, \
        number_LED, brightness, line_script_Wait, R_wait, G_wait, B_wait, R2_wait, G2_wait, B2_wait, initXaxis, \
        initYaxis, sizeXaxis, sizeYaxis, pixel, SPR, SYSCOF, filepath_settinh_client, filepath, setting_client

    # app = QApplication(sys.argv)
    # initialize_app(app)
        
    try:
        with new_socket() as server_socket:
            client_socket, addr = server_socket.accept()
            print('Connection address:', addr)

            autotest_client, flage_remove_cV, counter_client_play_video, counter_setting_request, \
                DIR, STEP, ENA, DEGSTEP, CW, CCW, MICROSTEP, FACTOR, MAX_SPEED_DELAY_small_dist, START_DELAY_small_dist, \
                FIN_DELAY_small_dist, MAX_SPEED_DELAY_long_dist, START_DELAY_long_dist, FIN_DELAY_long_dist, HALL, board_PIXEL, \
                number_LED, brightness, line_script_Wait, R_wait, G_wait, B_wait, R2_wait, G2_wait, B2_wait, initXaxis, \
                initYaxis, sizeXaxis, sizeYaxis, pixel, SPR, SYSCOF, specialNavigationRequests = setting_server(client_socket)


            initialize_gpio_pins(DIR, STEP, ENA, HALL, SPR, SYSCOF, MAX_SPEED_DELAY_small_dist, START_DELAY_small_dist, FIN_DELAY_small_dist, MAX_SPEED_DELAY_long_dist, START_DELAY_long_dist, FIN_DELAY_long_dist, CW, CCW, MICROSTEP, FACTOR, DEGSTEP)

            b = 0
            while b < number_LED:
                # pixel[b] = (GREEN)
                b = b + 1
                time.sleep(0.05)
            # pixel.fill(GREEN)

            onClient("Fluger запущен", client_socket)
            print("Fluger запущен\n")

            time.sleep(2)
            remove_createdVideos(flage_remove_cV)  # очищение папки createdVideos

            if not (autotest_client):
                pass
            else:
                z = 0
                while z < number_LED:
                    # pixel[z] = (YELLOW)
                    z = z + 1
                    time.sleep(0.05)
                # pixel.fill(YELLOW)

                # РАССКОММЕНТИРУЙ
                autotest_filename = "autotest_zastavka.mp4"
                set_Flag_LoopingVideoPlayer(False)
                thread_loopVideo = Thread(target=video, args=(find_file(autotest_filename), get_length(find_file(autotest_filename)), initXaxis, initYaxis, sizeXaxis, sizeYaxis, True))
                thread_loopVideo.start()
                set_Flag_LoopingVideoPlayer(autotest())
                thread_loopVideo.join()
                set_Flag_LoopingVideoPlayer(True)
                    
                a = 1
                while a < number_LED:
                    # pixel[-a] = (YELLOW)
                    a = a + 1
                    time.sleep(0.05)

            onClient("Fluger готов к работе", client_socket)
            print("Fluger готов к работе\n")
            waitingmode_start(R_wait, B_wait, G_wait, R2_wait, B2_wait, G2_wait)

            thread_client_request = Thread(target=client_request, )
            thread_client_request.start()

            while True:
                try:
                    
                    message_play_video = None
                    reqType, deg, namefile, screenplay, R, G, B, R2, G2, B2, necessarystep, setting = setting_request()

                    onClient("Получена команда от клиента", client_socket)
                    print("Получена команда от клиента\n")
                    thisstep = get_thisstep()
                    print(f"Шаг перед проверкой:{thisstep}")

                    print(f"_________________________________________Заход в обработчик вариантов представления, case: «{reqType}»_________________________________________")
                        
                    if reqType == 'navigation_null' and handle_navigation_null():
                        print(f"Запрос клиента выполнен: {setting}")
                        onClient("Запрос клиента выполнен", client_socket)
                        print(f"_________________________________________Переход на следующую иттерацию, case: «{reqType}»_________________________________________")
                        continue
                        
                    if reqType == 'performance' and handle_performance():
                        print(f"_________________________________________Переход на следующую иттерацию, case: «{reqType}»_________________________________________")
                        continue

                    if reqType == 'representation' and handle_representation():
                        print(f"_________________________________________Переход на следующую иттерацию, case: «{reqType}»_________________________________________")
                        continue
                    if not (reqType in ['performance', 'representation']) and handle_other_cases():
                        print(f"_________________________________________Переход на следующую иттерацию, case: «{reqType}»_________________________________________")
                        continue

                    time.sleep(.1)
                          
                    try:
                        if request_above(False):
                            continue
                    except Exception as e:
                        print("Error:", str(e))
                        
                    setting_client = get_setting_client()
                    if setting_client:
                        setting_client.pop(0)
                    filepath_settinh_client = get_filepath_settinh_client()
                    if filepath_settinh_client:
                        filepath_settinh_client.pop(0)

                    print(f"Очередь команд: {setting_client}")
                    # return_start()

                    print(f"Запрос клиента выполнен: {setting}")
                    onClient("Запрос клиента выполнен", client_socket)

                    print(f"_________________________________________Дошли до конца цикла: «{reqType}»_________________________________________")
                        
                except Exception as e:
                    print("An error occurred:", str(e))
                    continue
                    # raise
    
    except KeyboardInterrupt:
        print("Cleaning up!")
    finally:
        gpio.cleanup()
        if client_socket:
            client_socket.close()
        if server_socket:
            server_socket.close()


# Обработчик KeyboardInterrupt для корректного завершения приложения
def handle_interrupt():
    try:
        sys.exit(0)
    except SystemExit:
        os._exit(0)


if __name__ == "__main__":
    update_package_json()
    signal.signal(signal.SIGINT, lambda sig, frame: handle_interrupt())
    main()
    