#!/bin/sh

# Конфигурация
CACHE_DIR="/calista/cache"
DRIVER_LIST_URL="https://gitlab.svsptech.ru/svsptech/calista_drivers/raw/branch/main/driver.list"
DRIVER_LIST_FILE="$CACHE_DIR/driver.list"
REGISTRY_FILE="/calista/registry.db"
EXPECTED_VERSION="ver0"

# Создаём директорию кеша, если её нет
mkdir -p "$CACHE_DIR"

# Функция логирования в реестр
log_to_registry() {
    local type="$1"
    local details="$2"
    if [ -f "$REGISTRY_FILE" ]; then
        sqlite3 "$REGISTRY_FILE" "INSERT INTO calista_log (type, user, details)
                                  VALUES ('$type', '$USER', '$details');" 2>/dev/null
    fi
}

# Функция скачивания и обновления файла driver.list
update_driver_list() {
    echo "Обновление списка драйверов..."
    
    # Скачиваем файл во временный
    TEMP_FILE="$CACHE_DIR/driver.list.tmp"
    
    if fetch -o "$TEMP_FILE" "$DRIVER_LIST_URL" 2>/dev/null; then
        # Проверяем версию файла (первая строка)
        VERSION=$(head -1 "$TEMP_FILE" 2>/dev/null)
        
        if [ "$VERSION" != "$EXPECTED_VERSION" ]; then
            echo "Ошибка: Неподдерживаемая версия файла драйверов: $VERSION (ожидается $EXPECTED_VERSION)"
            log_to_registry "error" "Неподдерживаемая версия driver.list: $VERSION"
            rm -f "$TEMP_FILE"
            return 1
        fi
        
        # Перемещаем временный файл в основной
        mv "$TEMP_FILE" "$DRIVER_LIST_FILE"
        echo "Список драйверов обновлён (версия: $VERSION)"
        log_to_registry "info" "Список драйверов обновлён (версия: $VERSION)"
        return 0
    else
        echo "Ошибка: Не удалось скачать список драйверов"
        log_to_registry "error" "Не удалось скачать $DRIVER_LIST_URL"
        rm -f "$TEMP_FILE"
        return 1
    fi
}

# Функция поиска устройства в driver.list
# Возвращает полную строку из файла
find_device_in_list() {
    local vendor="$1"
    local device="$2"
    
    if [ ! -f "$DRIVER_LIST_FILE" ]; then
        return 1
    fi
    
    # Пропускаем первую строку (версия) и ищем точное совпадение
    grep -v "^ver" "$DRIVER_LIST_FILE" 2>/dev/null | grep "^${vendor}:${device}:" | head -1
}

# -------------------------------------------------------------------
# Команда: get_name
# Получение названия устройства по vendor и device
# -------------------------------------------------------------------
cmd_get_name() {
    local vendor="$1"
    local device="$2"
    
    if [ -z "$vendor" ] || [ -z "$device" ]; then
        echo "Ошибка: Не указаны vendor и device"
        exit 1
    fi
    
    # Проверяем наличие файла, если нет — скачиваем
    if [ ! -f "$DRIVER_LIST_FILE" ]; then
        echo "Файл driver.list не найден, скачиваем..."
        if ! update_driver_list; then
            echo "Неизвестное устройство"
            exit 1
        fi
    fi
    
    # Ищем устройство
    DEVICE_LINE=$(find_device_in_list "$vendor" "$device")
    
    if [ -n "$DEVICE_LINE" ]; then
        # Извлекаем название (третий столбец)
        DEVICE_NAME=$(echo "$DEVICE_LINE" | cut -d':' -f3)
        echo "$DEVICE_NAME"
    else
        echo "Неизвестное устройство"
    fi
}

# -------------------------------------------------------------------
# Команда: install
# Установка драйвера для устройства
# -------------------------------------------------------------------
cmd_install() {
    local vendor="$1"
    local device="$2"
    
    if [ -z "$vendor" ] || [ -z "$device" ]; then
        echo "Ошибка: Не указаны vendor и device"
        exit 1
    fi
    
    echo "Установка драйвера для $vendor:$device..."
    log_to_registry "info" "Начало установки драйвера для $vendor:$device"
    
    # Проверяем наличие файла, если нет — скачиваем
    if [ ! -f "$DRIVER_LIST_FILE" ]; then
        echo "Файл driver.list не найден, скачиваем..."
        if ! update_driver_list; then
            log_to_registry "error" "Не удалось скачать driver.list"
            exit 1
        fi
    fi
    
    # Ищем устройство
    DEVICE_LINE=$(find_device_in_list "$vendor" "$device")
    
    if [ -z "$DEVICE_LINE" ]; then
        echo "Ошибка: Устройство $vendor:$device не найдено в driver.list"
        log_to_registry "error" "Устройство $vendor:$device не найдено в driver.list"
        exit 1
    fi
    
    # Разбираем строку: vendor:device:name:type:url
    DEVICE_NAME=$(echo "$DEVICE_LINE" | cut -d':' -f3)
    DEVICE_TYPE=$(echo "$DEVICE_LINE" | cut -d':' -f4)
    DEVICE_URL=$(echo "$DEVICE_LINE" | cut -d':' -f5)
    
    echo "  Устройство: $DEVICE_NAME"
    echo "  Тип драйвера: $DEVICE_TYPE"
    
    # Проверяем тип драйвера
    if [ "$DEVICE_TYPE" = "builtin" ]; then
        echo "  Драйвер встроен в ядро FreeBSD, установка не требуется"
        log_to_registry "info" "Драйвер для $vendor:$device встроен в ядро"
        
        # Обновляем статус в реестре
        if [ -f "$REGISTRY_FILE" ]; then
            sqlite3 "$REGISTRY_FILE" "UPDATE devices SET status='installed'
                                      WHERE vendor='$vendor' AND device='$device';" 2>/dev/null
        fi
        exit 0
    fi
    
    # Проверяем тип https
    if [ "$DEVICE_TYPE" != "https" ]; then
        echo "Ошибка: Неподдерживаемый тип драйвера: $DEVICE_TYPE"
        log_to_registry "error" "Неподдерживаемый тип драйвера: $DEVICE_TYPE"
        exit 1
    fi
    
    if [ -z "$DEVICE_URL" ]; then
        echo "Ошибка: Не указана ссылка для скачивания"
        log_to_registry "error" "Не указана ссылка для скачивания драйвера"
        exit 1
    fi
    
    # Создаём директорию для драйвера
    DRIVER_CACHE_DIR="$CACHE_DIR/drivers/${vendor}_${device}"
    mkdir -p "$DRIVER_CACHE_DIR"
    
    # Скачиваем архив
    echo "  Скачивание драйвера из $DEVICE_URL..."
    ARCHIVE_FILE="$DRIVER_CACHE_DIR/driver.zip"
    
    if fetch -o "$ARCHIVE_FILE" "https://$DEVICE_URL" 2>/dev/null; then
        echo "  Архив скачан: $ARCHIVE_FILE"
    else
        echo "Ошибка: Не удалось скачать архив"
        log_to_registry "error" "Не удалось скачать архив $DEVICE_URL"
        exit 1
    fi
    
    # Распаковываем архив
    echo "  Распаковка архива..."
    EXTRACT_DIR="$DRIVER_CACHE_DIR/extracted"
    mkdir -p "$EXTRACT_DIR"
    
    # Определяем тип архива по расширению
    case "$ARCHIVE_FILE" in
        *.zip)
            if ! unzip -q "$ARCHIVE_FILE" -d "$EXTRACT_DIR" 2>/dev/null; then
                echo "Ошибка: Не удалось распаковать zip-архив"
                log_to_registry "error" "Не удалось распаковать zip-архив"
                exit 1
            fi
            ;;
        *.tar.gz|*.tgz)
            if ! tar -xzf "$ARCHIVE_FILE" -C "$EXTRACT_DIR" 2>/dev/null; then
                echo "Ошибка: Не удалось распаковать tar.gz-архив"
                log_to_registry "error" "Не удалось распаковать tar.gz-архив"
                exit 1
            fi
            ;;
        *.tar)
            if ! tar -xf "$ARCHIVE_FILE" -C "$EXTRACT_DIR" 2>/dev/null; then
                echo "Ошибка: Не удалось распаковать tar-архив"
                log_to_registry "error" "Не удалось распаковать tar-архив"
                exit 1
            fi
            ;;
        *)
            echo "Ошибка: Неизвестный формат архива"
            log_to_registry "error" "Неизвестный формат архива: $ARCHIVE_FILE"
            exit 1
            ;;
    esac
    
    echo "  Архив распакован в $EXTRACT_DIR"
    
    # Ищем файл build в распакованной директории
    BUILD_SCRIPT=$(find "$EXTRACT_DIR" -name "build" -type f -executable 2>/dev/null | head -1)
    
    if [ -z "$BUILD_SCRIPT" ]; then
        echo "Ошибка: Файл build не найден в архиве"
        log_to_registry "error" "Файл build не найден в архиве"
        exit 1
    fi
    
    BUILD_DIR=$(dirname "$BUILD_SCRIPT")
    
    # Выполняем сборку
    echo "  Запуск сборки драйвера..."
    echo "  Рабочая директория: $BUILD_DIR"
    
    cd "$BUILD_DIR" || {
        echo "Ошибка: Не удалось перейти в директорию $BUILD_DIR"
        log_to_registry "error" "Не удалось перейти в директорию $BUILD_DIR"
        exit 1
    }
    
    if ./build; then
        echo "  Сборка драйвера завершена успешно"
        log_to_registry "info" "Драйвер для $vendor:$device установлен успешно"
        
        # Обновляем статус в реестре
        if [ -f "$REGISTRY_FILE" ]; then
            sqlite3 "$REGISTRY_FILE" "UPDATE devices SET status='installed_calista', name='$DEVICE_NAME' 
                                      WHERE vendor='$vendor' AND device='$device';" 2>/dev/null
        fi
        
        exit 0
    else
	if [ -f "$REGISTRY_FILE" ]; then
            sqlite3 "$REGISTRY_FILE" "UPDATE devices SET status='installed_calista_error', name='$DEVICE_NAME'
                                      WHERE vendor='$vendor' AND device='$device';" 2>/dev/null
        fi

        echo "Ошибка: Сборка драйвера завершилась с ошибкой"
        log_to_registry "error" "Сборка драйвера для $vendor:$device завершилась с ошибкой"
        exit 1
    fi
}

# -------------------------------------------------------------------
# Команда: update_list
# Принудительное обновление списка драйверов
# -------------------------------------------------------------------
cmd_update_list() {
    echo "Принудительное обновление списка драйверов..."
    if update_driver_list; then
        echo "Список драйверов успешно обновлён"
        exit 0
    else
        echo "Ошибка обновления списка драйверов"
        exit 1
    fi
}

# -------------------------------------------------------------------
# Точка входа
# -------------------------------------------------------------------
main() {
    local command="$1"
    local vendor="$2"
    local device="$3"
    
    case "$command" in
        get_name)
            cmd_get_name "$vendor" "$device"
            ;;
        install)
            cmd_install "$vendor" "$device"
            ;;
        update_list)
            cmd_update_list
            ;;
        *)
            echo "Использование:"
            echo "  $0 get_name <vendor> <device>     - получить название устройства"
            echo "  $0 install <vendor> <device>       - установить драйвер"
            echo "  $0 update_list                     - обновить список драйверов"
            echo ""
            echo "Пример:"
            echo "  $0 get_name 0x10de 0x0398"
            echo "  $0 install 0x10de 0x0398"
            exit 1
            ;;
    esac
}

main "$@"
