internal static DriverResponse HandleDriverRequest(DriverRequest request)
        {
            var response = new DriverResponse {
                method = request.method
            };
            var session = GetSession();

            switch (request.method.ToLowerInvariant())
            {
            case "registereditor":
                if (string.IsNullOrEmpty(session))
                {
                        #if UNITY_EDITOR
                    SaveSession(request.session);
                        #endif

                    response.session = request.session;
                }
                else
                {
                    response.session = session;
                }

                response.result = "unity";
                break;

            case "exist":
                response.result = MainThreadHelper.ExecuteGameObjectEmulation(request.upath,
                                                                              gameObject => true.ToString());
                break;

            case "active":
                response.result = MainThreadHelper.ExecuteGameObjectEmulation(request.upath,
                                                                              gameObject => gameObject.activeInHierarchy.ToString());
                break;

            case "onscreen":
                response.result = MainThreadHelper.ExecuteGameObjectEmulation(request.upath, gameObject => ScreenHelper.IsOnScreen(gameObject).ToString());
                break;

            case "graphicclickable":
                response.result = MainThreadHelper.ExecuteGameObjectEmulation(request.upath, gameObject => ScreenHelper.IsGraphicClickable(gameObject).ToString());
                break;

            case "physicclickable":
                response.result = MainThreadHelper.ExecuteGameObjectEmulation(request.upath, gameObject => ScreenHelper.IsPhysicClickable(gameObject).ToString());
                break;

            case "getcomponent":
                response.result = MainThreadHelper.ExecuteGameObjectEmulation(request.upath, gameObject =>
                {
                    var component = gameObject.GetComponent(request.value);
                    return(component != null ? JsonUtility.ToJson(component) : "null");
                });
                break;

            case "click":
                response.result = MainThreadHelper.ExecuteGameObjectEmulation(request.upath, gameObject =>
                {
                    var pointer = new PointerEventData(EventSystem.current);
                    ExecuteEvents.Execute(gameObject, pointer, ExecuteEvents.pointerClickHandler);
                    return(ErrorMessages.SuccessResult);
                });
                break;

            case "isrendering":
                response.result = MainThreadHelper.ExecuteGameObjectEmulation(request.upath,
                                                                              go =>
                {
                    var renderer = go.GetComponent <Renderer>();
                    if (renderer != null)
                    {
                        return(renderer.isVisible.ToString());
                    }

                    return(false.ToString());
                });
                break;

            case "getscene":
                response.result = MainThreadHelper.InvokeOnMainThreadAndWait(() => SceneManager.GetActiveScene().name);
                break;

            case "openscene":
                response.result = MainThreadHelper.InvokeOnMainThreadAndWait(
                    () =>
                {
                    try
                    {
                        SceneManager.LoadScene(request.key);
                        return(ErrorMessages.SuccessResult);
                    }
                    catch (Exception e)
                    {
                        return(e.ToString());
                    }
                });
                break;

            case "count":
                response.result = MainThreadHelper.ExecuteGameObjectsEmulation(request.upath, goList => goList.Count.ToString());
                break;

            case "deleteplayerpref":
                response.result = MainThreadHelper.InvokeOnMainThreadAndWait(() =>
                {
                    PlayerPrefs.DeleteKey(request.key);
                    PlayerPrefs.Save();
                });
                break;

            case "deleteallprefs":
                response.result = MainThreadHelper.InvokeOnMainThreadAndWait(() =>
                {
                    PlayerPrefs.DeleteAll();
                    PlayerPrefs.Save();
                });
                break;

            case "getfloatplayerpref":
                response.result = MainThreadHelper.InvokeOnMainThreadAndWait(() => PlayerPrefs.GetFloat(request.key).ToString(CultureInfo.InvariantCulture));
                break;

            case "getintplayerpref":
                response.result = MainThreadHelper.InvokeOnMainThreadAndWait(() => PlayerPrefs.GetInt(request.key).ToString());
                break;

            case "getstringplayerpref":
                response.result = MainThreadHelper.InvokeOnMainThreadAndWait(() => PlayerPrefs.GetString(request.key));
                break;

            case "setfloatplayerpref":
                response.result = MainThreadHelper.InvokeOnMainThreadAndWait(() =>
                {
                    var result = ErrorMessages.SuccessResult;
                    try
                    {
                        PlayerPrefs.SetFloat(request.key, float.Parse(request.value));
                        PlayerPrefs.Save();
                    }
                    catch (Exception e)
                    {
                        result = e.ToString();
                    }
                    return(result);
                });
                break;

            case "setintplayerpref":
                response.result = MainThreadHelper.InvokeOnMainThreadAndWait(() =>
                {
                    var result = ErrorMessages.SuccessResult;
                    try
                    {
                        PlayerPrefs.SetInt(request.key, int.Parse(request.value));
                        PlayerPrefs.Save();
                    }
                    catch (Exception e)
                    {
                        result = e.ToString();
                    }
                    return(result);
                });
                break;

            case "setstringplayerpref":
                response.result = MainThreadHelper.InvokeOnMainThreadAndWait(() =>
                {
                    var result = ErrorMessages.SuccessResult;
                    try
                    {
                        PlayerPrefs.SetFloat(request.key, float.Parse(request.value));
                        PlayerPrefs.Save();
                    }
                    catch (Exception e)
                    {
                        result = e.ToString();
                    }
                    return(result);
                });
                break;

            case "playerprefhaskey":
                response.result = MainThreadHelper.InvokeOnMainThreadAndWait(() =>
                {
                    string result;
                    try
                    {
                        result = PlayerPrefs.HasKey(request.key).ToString();
                    }
                    catch (Exception e)
                    {
                        result = e.ToString();
                    }
                    return(result);
                });
                break;

            case "getcoordinates":
                response.result = MainThreadHelper.ExecuteGameObjectEmulation(request.upath, gameObject =>
                {
                    var position    = ScreenHelper.GetPositionOnScreen(gameObject, Camera.main);
                    var coordinates = new ScreenCoordinates {
                        X = position.x, Y = position.y
                    };
                    return(JsonUtility.ToJson(coordinates));
                });
                break;

            case "swipe":
                var swipeDirection = Vector2.zero;
                switch (request.value)
                {
                case "up":
                    swipeDirection = Vector2.up;
                    break;

                case "down":
                    swipeDirection = Vector2.down;
                    break;

                case "left":
                    swipeDirection = Vector2.left;
                    break;

                case "right":
                    swipeDirection = Vector2.right;
                    break;
                }

                swipeDirection *= 100;

                response.result = MainThreadHelper.ExecuteGameObjectEmulation(request.upath, gameObject => {
                    var pointer = new PointerEventData(EventSystem.current);
                    gameObject.GetComponent <MonoBehaviour>().StartCoroutine(DragCoroutine(gameObject, pointer, (Vector2)ScreenHelper.GetPositionOnScreen(gameObject, Camera.main) + swipeDirection * 2));

                    return(ErrorMessages.SuccessResult);
                });
                break;

            case "dragto":
                response.result = MainThreadHelper.ExecuteGameObjectEmulation(request.upath, gameObject => {
                    var screenCoordinates = new ScreenCoordinates();
                    JsonUtility.FromJsonOverwrite(request.value, screenCoordinates);
                    var pointer = new PointerEventData(EventSystem.current);
                    gameObject.GetComponent <MonoBehaviour>().StartCoroutine(DragCoroutine(gameObject, pointer,
                                                                                           new Vector2 {
                        x = screenCoordinates.X, y = screenCoordinates.Y
                    }));

                    return("OK");
                });
                break;


            case "sendkeys":
                response.result = MainThreadHelper.ExecuteGameObjectEmulation(request.upath, gameObject =>
                {
                    var input = gameObject.GetComponent <InputField>();
                    if (input != null)
                    {
                        input.text = request.value;
                    }
                    else
                    {
                        var tmpInput = gameObject.GetComponent <TMP_InputField>();
                        if (tmpInput != null)
                        {
                            tmpInput.text = request.value;
                        }
                        else
                        {
                            return("input not found");
                        }
                    }

                    return(ErrorMessages.SuccessResult);
                });
                break;

            case "startplaymode":
#if UNITY_EDITOR
                EditorApplication.update += StartPlayMode;
                response.result           = ErrorMessages.SuccessResult;
#else
                response.result = ErrorMessages.MethodIsNotSupported;
#endif
                break;

            case "stopplaymode":
#if UNITY_EDITOR
                response.result = MainThreadHelper.InvokeOnMainThreadAndWait(() =>
                {
                    //EditorApplication.UnlockReloadAssemblies();
                    EditorApplication.isPlaying = false;
                });
#else
                response.result = ErrorMessages.MethodIsNotSupported;
#endif
                break;

            case "ping":
                response.result = "pong";
                break;

            case "takescreenshot":
                var path = request.value;
                response.result = MainThreadHelper.InvokeOnMainThreadAndWait(() => { TakeScreenshot(path); });
                break;

            case "isplaymode":
                response.result = MainThreadHelper.InvokeOnMainThreadAndWait(() => Application.isPlaying.ToString());
                break;

            case "gamecustom":
                response.result = CustomDriverHandler.ProcessGameCustomMethod(request.key, request.value);
                break;

            case "gameobjectcustom":
                response.result = CustomDriverHandler.ProcessGameObjectCustomMethod(request.upath, request.key, request.value);
                break;

            default:
                response.result = "Unknown method " + request.method + ".";
                break;
            }

            return(response);
        }