import gxipy as gx
import cv2
import numpy as np
import time


def main():
    print("Инициализация камер...")
    
    # Создаем менеджер устройств
    device_manager = gx.DeviceManager()
    dev_num, dev_info_list = device_manager.update_all_device_list()
    
    if dev_num < 2:
        print("Найдено только %d камер. Нужно 2 камеры!" % dev_num)
        return

    # Открываем обе камеры
    cam1 = device_manager.open_device_by_index(1)
    cam2 = device_manager.open_device_by_index(2)
    
    # Список разрешений (ширина, высота) для переключения
    resolutions = [
        (640, 480),
        (800, 600), 
        (1024, 768),
        (1280, 960),
        (1440, 1080)
    ]
    current_res_index = 0
    
    # Переменные для FPS и статистики
    fps1 = 0
    fps2 = 0
    frame_count1 = 0
    frame_count2 = 0
    last_time = time.time()
    
    def set_resolution(cam1, cam2, width, height, cam_num):
        try:
            cam1.stream_off()
            cam2.stream_off()
            
            cam1.Width.set(width)
            cam1.Height.set(height)
            cam2.Width.set(width)
            cam2.Height.set(height)
            
            cam1.stream_on()
            cam2.stream_on()
            
            print("Камеры %d: установлено разрешение %dx%d" % (cam_num, width, height))
            return True
        except Exception as e:
            print("Ошибка установки разрешения: %s" % str(e))
            # Пробуем перезапустить стримы даже при ошибке
            try:
                cam1.stream_on()
                cam2.stream_on()
            except:
                pass
            return False
                # Проверяем настройки камер
    print("Проверка настроек камер:")
    try:
        pixel_format = cam1.PixelFormat.get()
        print("Pixel format:", pixel_format)
    except:
        pass

    try:
        compression_mode = cam1.CompressionMode.get()
        print("Compression mode:", compression_mode)
    except:
        pass

    try:
        acquisition_mode = cam1.AcquisitionMode.get()
        print("Acquisition mode:", acquisition_mode)
    except:
        pass
    try:
        bandwidth_feature = cam1.get_remote_device_feature_control().get_int_feature("Bandwidth")
        bandwidth = bandwidth_feature.get()
        print("Bandwidth:", bandwidth)
    except:
        pass
    try:
        bandwidth_feature = cam1.get_remote_device_feature_control().get_float_feature("Bandwidth")
        bandwidth_value = bandwidth_feature.get()
        print("Bandwidth:", bandwidth_value)
    except Exception as e:
        print("Bandwidth не работает:", e)
        
    try:
        data_rate_feature = cam1.get_remote_device_feature_control().get_int_feature("DataRate") 
        data_rate = data_rate_feature.get()
        print("DataRate:", data_rate)
    except:
        pass       

    try:
        stream_statistics = cam1.get_stream_statistics()
        print("Stream stats:", stream_statistics)
    except:
        pass   


    try:
        throughput_feature = cam1.get_remote_device_feature_control().get_int_feature("DeviceLinkCurrentThroughput")
        current_value = throughput_feature.get()
        print("DeviceLinkCurrentThroughput raw value:", current_value)
    
        # Попробуем разные варианты интерпретации
        print("Как Мбит/с:", current_value / 1000000.0)
        print("Как Кбит/с:", current_value / 1000.0)
        print("Как байт/с:", current_value)
        print("Как процент:", current_value, "%")
    
        # Может это текущий FPS?
        print("Как FPS:", current_value)
    
    except Exception as e:
        print("Ошибка:", e)        
    
    # Устанавливаем начальное разрешение
    width, height = resolutions[current_res_index]
    set_resolution(cam1, cam2, width, height, 1)
    
    remote_device_feature1 = cam1.get_remote_device_feature_control()
    remote_device_feature2 = cam2.get_remote_device_feature_control()    
    
    # Только читаем текущие значения для каждой камеры
    exposure_time_feature1 = remote_device_feature1.get_float_feature("ExposureTime") 
    exposure_time_feature2 = remote_device_feature2.get_float_feature("ExposureTime")    
    print("Камера 1 экспозиция: %s" % exposure_time_feature1.get())
    print("Камера 2 экспозиция: %s" % exposure_time_feature2.get())    
    gain_value1 = remote_device_feature1.get_float_feature("Gain")
    gain_value2 = remote_device_feature2.get_float_feature("Gain")
    print("Камера 1 gain: %s" % gain_value1.get())
    print("Камера 2 gain: %s" % gain_value2.get())
    
    # Настраиваем обе камеры
    for cam in [cam1, cam2]:
        cam.TriggerMode.set(0)  # Непрерывный режим
    
    print("Горячие клавиши:")
    print("'w' - увеличить разрешение")
    print("'s' - уменьшить разрешение") 
    print("'q' - выход")
    print("Текущее разрешение: %dx%d" % (width, height))

    try:
        while True:
            # Обновляем FPS и скорость КАЖДЫЙ КАДР, но сглаживаем
            current_time = time.time()
            time_diff = current_time - last_time
            
            # Сглаживание FPS (бегущее среднее)
            if time_diff > 0:
                current_fps1 = 1.0 / time_diff if frame_count1 > 0 else 0
                current_fps2 = 1.0 / time_diff if frame_count2 > 0 else 0
                
                # Бегущее среднее для плавности
                fps1 = fps1 * 0.9 + current_fps1 * 0.1
                fps2 = fps2 * 0.9 + current_fps2 * 0.1
            
            last_time = current_time
            
            # Получаем реальную скорость КАЖДЫЙ КАДР
            # Получаем реальную скорость КАЖДЫЙ КАДР
            real_speed1 = 0
            real_speed2 = 0
# Конвертация DeviceLinkCurrentThroughput (байты/сек) в Мбит/сек
# Используется бинарная система счисления (степени 2), а не SI (степени 10)
# 
# 131072 = 2^17 = 1024 * 1024 / 8
# Где:
#   - 1024 * 1024 = 1 MiB (мегабайт в бинарной системе)
#   - / 8 = конвертация байтов в биты
# 
# Таким образом: байты/сек / 131072 = Мбит/сек (бинарные)
# 
# Производители USB3 Vision камер используют бинарные мегабиты вместо
# стандартных SI мегабит (где делитель был бы 1_000_000 / 8 = 125_000)
# потому что USB работает с пакетами размером в степенях 2.
# 
# Разница между системами:
#   SI (сети):     байты/сек * 8 / 1_000_000 = Mbps (decimal)
#   Binary (USB):  байты/сек / 131_072 = Mbps (binary)
#   Разница: ~4.9% (1024^2 / 1000^2 ≈ 1.049)
# 
# +0.05 - округление для корректного отображения дробной части            
            try:
                throughput_feature1 = cam1.get_remote_device_feature_control().get_int_feature("DeviceLinkCurrentThroughput")
                #real_speed1 = (throughput_feature1.get() * 8) / 1000000.0  # Мбит/с
                real_speed1 = (throughput_feature1.get() / 131072.0) + 0.05
            except:
                pass
                
            try:
                throughput_feature2 = cam2.get_remote_device_feature_control().get_int_feature("DeviceLinkCurrentThroughput")
                #real_speed2 = (throughput_feature2.get() * 8) / 1000000.0  # Мбит/с
                real_speed2 = (throughput_feature2.get() / 131072.0) + 0.05
            except:
                pass
            
            # Получаем изображения с обеих камер
            raw_image1 = cam1.data_stream[0].get_image()
            raw_image2 = cam2.data_stream[0].get_image()
            
            # Обрабатываем первую камеру
            if raw_image1 is not None:
                numpy_image1 = raw_image1.get_numpy_array()
                if numpy_image1 is not None:
                    frame_count1 += 1
                    
                    # Добавляем текст с информацией поверх изображения
                    display_img1 = numpy_image1.copy()
                    
                    # Создаем многострочный текст
                    info_texts = [
                        "Res: %dx%d" % (width, height),
                        "FPS: %.1f" % fps1,
                        "Data: %.1f Mbps" % real_speed1
                    ]
                    
                    # Отображаем каждую строку текста
                    y_offset = 30
                    for text in info_texts:
                        cv2.putText(display_img1, text, (10, y_offset), 
                                   cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2)
                        y_offset += 25
                    
                    cv2.imshow('Camera 1', display_img1)
            
            # Обрабатываем вторую камеру
            if raw_image2 is not None:
                numpy_image2 = raw_image2.get_numpy_array()
                if numpy_image2 is not None:
                    frame_count2 += 1
                    
                    display_img2 = numpy_image2.copy()
                    
                    # Создаем многострочный текст
                    info_texts = [
                        "Res: %dx%d" % (width, height),
                        "FPS: %.1f" % fps2,
                        "Data: %.1f Mbps" % real_speed2
                    ]
                    
                    # Отображаем каждую строку текста
                    y_offset = 30
                    for text in info_texts:
                        cv2.putText(display_img2, text, (10, y_offset), 
                                   cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2)
                        y_offset += 25
                    
                    cv2.imshow('Camera 2', display_img2)
            
            # Обработка горячих клавиш
            key = cv2.waitKey(1) & 0xFF
            
            if key == ord('q'):
                break
            elif key == ord('w'):  # W - увеличить разрешение
                if current_res_index < len(resolutions) - 1:
                    current_res_index += 1
                    width, height = resolutions[current_res_index]
                    if set_resolution(cam1, cam2, width, height, current_res_index + 1):
                        print("Текущее разрешение: %dx%d" % (width, height))
                        # Сбрасываем счетчики FPS при смене разрешения
                        frame_count1 = 0
                        frame_count2 = 0
                        last_time = time.time()
            elif key == ord('s'):  # S - уменьшить разрешение
                if current_res_index > 0:
                    current_res_index -= 1
                    width, height = resolutions[current_res_index]
                    if set_resolution(cam1, cam2, width, height, current_res_index + 1):
                        print("Текущее разрешение: %dx%d" % (width, height))
                        # Сбрасываем счетчики FPS при смене разрешения
                        frame_count1 = 0
                        frame_count2 = 0
                        last_time = time.time()
                
    except KeyboardInterrupt:
        print("Прервано пользователем")
    
    finally:
        # Очистка
        cv2.destroyAllWindows()
        cam1.stream_off()
        cam2.stream_off()
        cam1.close_device()
        cam2.close_device()
        print("Камеры отключены")


if __name__ == "__main__":
    main()