//-------------------------------------------------------------------------------------------------
ALVR_RESULT HandleKeyboard(UINT_PTR ch)
{
    if(ch == 'E' || ch == 'e')
    {
        g_MouseInput.SetEmulation(!g_MouseInput.GetEmulation());
    }
    else if(ch == 'L' || ch == 'l')
    {
        g_bLateLatchRight = !g_bLateLatchRight;
    }
    else if(ch == 'A' || ch == 'a')
    {
        g_bRotate = !g_bRotate;
    }

    else if(ch == VK_UP)
    {
        ChangeDrawRepeat(true);
    }
    else if(ch == VK_DOWN)
    {
        ChangeDrawRepeat(false);
    }
    else
    {
        return ALVR_FALSE;
    }
    return ALVR_OK;
}
//-------------------------------------------------------------------------------------------------
ALVR_RESULT Init()
{
    HRESULT hr = S_OK;

    //---------------------------------------------------------------------------------------------
    // Init ALVR
    //---------------------------------------------------------------------------------------------

    ALVR_RESULT res = ALVR_OK;
    g_hLiquidVRDLL = LoadLibraryW(ALVR_DLL_NAME);
    CHECK_RETURN(g_hLiquidVRDLL != NULL, ALVR_FAIL, L"DLL " << ALVR_DLL_NAME << L" is not found");


    ALVRInit_Fn pInit = (ALVRInit_Fn)GetProcAddress(g_hLiquidVRDLL, ALVR_INIT_FUNCTION_NAME);
    res = pInit(ALVR_FULL_VERSION, (void**)&g_pFactory);
    CHECK_ALVR_ERROR_RETURN(res, ALVR_INIT_FUNCTION_NAME << L"failed");

#if defined(AFFINITY_WORK_AROUND)

    res = g_pFactory->CreateGpuAffinity(&m_pLvrAffinity);
    //    CHECK_ALVR_ERROR_RETURN(res, L"CreateGpuAffinity() failed");

    if(m_pLvrAffinity != NULL)
    {
        res = m_pLvrAffinity->EnableGpuAffinity(ALVR_GPU_AFFINITY_FLAGS_NONE);
        CHECK_ALVR_ERROR_RETURN(res, L"EnableGpuAffinity() failed");

        res = m_pLvrAffinity->DisableGpuAffinity();
        CHECK_ALVR_ERROR_RETURN(res, L"EnableGpuAffinity() failed");
    }
#endif

    //---------------------------------------------------------------------------------------------
    // create D3D11 device
    //---------------------------------------------------------------------------------------------
    res = g_D3DHelper.CreateD3D11Device();
    CHECK_ALVR_ERROR_RETURN(res, L"CreateD3D11Device() failed");


    res = g_pFactory->CreateALVRDeviceExD3D11(g_D3DHelper.m_pd3dDevice, NULL, &g_pLvrDevice);
    CHECK_ALVR_ERROR_RETURN(res, L"CreateALVRDeviceExD3D11() failed");

    res = g_pLvrDevice->CreateFence(&g_pFenceD3D11);
    CHECK_ALVR_ERROR_RETURN(res, L"CreateFence() failed");

    //---------------------------------------------------------------------------------------------
    // create window
    //---------------------------------------------------------------------------------------------
    HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);

    WNDCLASSEX wcex     = {0};
    wcex.cbSize         = sizeof(WNDCLASSEX);
    wcex.style          = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wcex.lpfnWndProc    = MyDefWindowProcW;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = NULL;
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszClassName  = L"SimpleMGPU";
    wcex.hIconSm        = NULL;

    RegisterClassEx(&wcex);

    int posX = 0;
    int posY = 0;

    UINT count=0;
    int adapterIDLocal = 0;

    DISPLAY_DEVICE displayDevice;
    displayDevice.cb = sizeof(displayDevice);

    while(true)
    {

        if(EnumDisplayDevices(NULL, count, &displayDevice, 0) == FALSE)
        {
            break;
        }
        if(displayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE)
        {
            if(displayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
            {
                break;
            }
            adapterIDLocal++;
        }
        count++;
    }
    EnumDisplayMonitors(NULL, NULL, MyDisplayEnumProc, (LPARAM)displayDevice.DeviceName);
    // find adapter and provide coordinates
    unsigned int width =  (g_MonitorWorkArea.right - g_MonitorWorkArea.left) * 2 / 3;
    unsigned int height =  (g_MonitorWorkArea.bottom - g_MonitorWorkArea.top) * 2 / 3;
    posX = (g_MonitorWorkArea.left + g_MonitorWorkArea.right) / 2 - width / 2;
    posY = (g_MonitorWorkArea.top + g_MonitorWorkArea.bottom) / 2 - height / 2;

    //    GetWindowPosition(posX, posY);
    g_hWindow = CreateWindow(L"SimpleMGPU", L"SimpleMGPU", WS_POPUP,
                             posX, posY, width, height, NULL, NULL, hInstance, NULL);
    CHECK_RETURN(g_hWindow != NULL, ALVR_FAIL, L"Window failed to create");

    ::ShowWindow(g_hWindow, SW_NORMAL);
    ::UpdateWindow(g_hWindow);

    //---------------------------------------------------------------------------------------------
    // Create swap chain
    //---------------------------------------------------------------------------------------------

    res = g_D3DHelper.CreateSwapChain(g_hWindow, g_iBackbufferCount);
    CHECK_ALVR_ERROR_RETURN(res, L"CreateSwapChain() failed");

    //---------------------------------------------------------------------------------------------
    // prepare 3D scene
    //---------------------------------------------------------------------------------------------
    res = g_D3DHelper.Create3DScene(width, height, true);
    CHECK_ALVR_ERROR_RETURN(res, L"Create3DScene() failed");

    g_MouseInput.Init((HINSTANCE)GetModuleHandle(NULL), g_hWindow, &g_D3DHelper, 200);
    g_MouseInput.SetEmulation(true);

    return ALVR_OK;
}