import subprocess
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 signal
from datetime import datetime

from threading import Lock
from video_player import add_scroll_text, client_play_video, find_file, get_length, get_timeout, initialize_special_videos, \
    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 cleanup_and_restart, get_message_play_video, get_setting_client, log_message, new_socket, setting_server, \
    onClient, request_above, \
    client_request, setting_request, join_thread, \
    filepath_setting_request, \
    get_filepath_settinh_client, send_ping

lock = Lock()

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:
        log_message('Зашли в navig_null and thisstep=0')  
        print('Зашли в navig_null and thisstep=0')
        setting_client = get_setting_client()
        time.sleep(.1)

        join_thread()
        return False
    else:
        print('Зашли в navig_null in ELSE')
        log_message('Зашли в 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}")
        log_message(f"Очередь команд: {setting_client}")
        join_thread()
        return False    


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

    log_message('Запущен performance')
    print('Запущен performance')
    join_thread()  # Завершение всех текущих потоков перед запуском новых операций

    filepath = filepath_setting_request()
    log_message("Ждем команду для воспроизведения видео")
    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)
        return False
    
    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:
        log_message(str(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:
        log_message('Отсутствует видеофайл для воспроизведения. Не запускаем видеоплеер')
        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

    log_message('Не запущен performance')
    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))
        log_message(str(e))


    filepath_settinh_client = get_filepath_settinh_client()
    filepath = filepath_setting_request()

    log_message("Ждем команду для воспроизведения видео")
    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)
            #
            return False
    except Exception as e:
        print("Error:", str(e))
        log_message(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:
        log_message('Отсутствует видеофайл для воспроизведения. Не запускаем видеоплеер')
        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')
    log_message('Запущен 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)

    try:
        if request_above(False):
            join_thread()
            set_Flag_LoopingVideoPlayer(True)
            thread_loopVideo.join()
            set_Flag_LoopingVideoPlayer(True)    
            return True
    except Exception as e:
        join_thread()
        set_Flag_LoopingVideoPlayer(True)
        thread_loopVideo.join()
        set_Flag_LoopingVideoPlayer(True)    
        print("Error:", str(e))
        log_message(str(e))

    thisstep = get_thisstep()
    set_Flag_LoopingVideoPlayer(steppermovement(necessarystep, flag_onClient, thisstep))
    try:
        if request_above(False):
            join_thread()
            set_Flag_LoopingVideoPlayer(True)
            thread_loopVideo.join()
            set_Flag_LoopingVideoPlayer(True)    
            return True
    except Exception as e:
        join_thread()
        thread_loopVideo.join()
        set_Flag_LoopingVideoPlayer(True)
        thread_loopVideo.join()
        set_Flag_LoopingVideoPlayer(True)    
        print("Error:", str(e))
        log_message(str(e))
        
    join_thread()
    thread_loopVideo.join()
    set_Flag_LoopingVideoPlayer(True)

    try:
        if request_above(False):
            return True
    except Exception as e:
        print("Error:", str(e))
        log_message(str(e))

    filepath_settinh_client = get_filepath_settinh_client()
    print("Лопасть готова к презентации")
    log_message("Лопасть готова к презентации")
    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)
            return False

    except Exception as e:
        print("Error:", str(e))
        log_message(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))
        log_message(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('Отсутствует видеофайл для воспроизведения. Не запускаем видеоплеер')
        log_message('Отсутствует видеофайл для воспроизведения. Не запускаем видеоплеер')
        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)
            log_message(f'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)
            log_message("Fluger запущен")
            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()
                
                thread_InitializeVideos = Thread(target=initialize_special_videos)
                thread_InitializeVideos.start()

                set_Flag_LoopingVideoPlayer(autotest())
                
                thread_InitializeVideos.join()
                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")
            log_message("Fluger готов к работе")
            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")
                    log_message("Получена команда от клиента")
                    thisstep = get_thisstep()
                    print(f"Шаг перед проверкой:{thisstep}")

                    log_message(f"_________________________________________Заход в обработчик вариантов представления, case: «{reqType}»_________________________________________")
                    print(f"_________________________________________Заход в обработчик вариантов представления, case: «{reqType}»_________________________________________")
                        
                    if reqType == 'navigation_null' and handle_navigation_null():
                        print(f"_________________________________________Переход на следующую иттерацию, case: «{reqType}»_________________________________________")
                        log_message(f"_________________________________________Переход на следующую иттерацию, case: «{reqType}»_________________________________________")
                        continue
                        
                    if reqType == 'performance' and handle_performance():
                        print(f"_________________________________________Переход на следующую иттерацию, case: «{reqType}»_________________________________________")
                        log_message(f"_________________________________________Переход на следующую иттерацию, case: «{reqType}»_________________________________________")
                        continue

                    if reqType == reqType in ['idle_representation', 'representation'] and handle_representation():
                        print(f"_________________________________________Переход на следующую иттерацию, case: «{reqType}»_________________________________________")
                        log_message(f"_________________________________________Переход на следующую иттерацию, case: «{reqType}»_________________________________________")
                        continue
                    if not (reqType in ['performance', 'representation', 'navigation_null']) and handle_other_cases():
                        print(f"_________________________________________Переход на следующую иттерацию, case: «{reqType}»_________________________________________")
                        log_message(f"_________________________________________Переход на следующую иттерацию, case: «{reqType}»_________________________________________")
                        continue
                    
                    # return_start()
                    time.sleep(.1)
                          
                    try:
                        if request_above(False):
                            continue
                    except Exception as e:
                        print("Error:", str(e))
                        log_message(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}")
                    log_message(f"Очередь команд: {setting_client}")                    

                    print(f"Запрос клиента выполнен: {setting}")
                    onClient("Запрос клиента выполнен", client_socket)
                    log_message(f"Запрос клиента выполнен: {setting}")
                    
                    print(f"_________________________________________Дошли до конца цикла: «{reqType}»_________________________________________")
                    log_message(f"_________________________________________Дошли до конца цикла: «{reqType}»_________________________________________")                        
                except Exception as e:
                    print("An error occurred:", str(e))
                    log_message("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__":
    signal.signal(signal.SIGINT, lambda sig, frame: handle_interrupt())
    # log_file = setup_logging()      
    main()
    