public function process()
    {
        $this->validate();

        $ref = ($this->getRequestParameter('ref') === false) ? null : $this->getRequestParameter('ref');
        $direction = $this->getRequestParameter('direction');
        $scope = $this->getRequestParameter('scope');
        $start = ($this->getRequestParameter('start') !== false);

        try {
            /** @var QtiRunnerServiceContext $serviceContext */
            $serviceContext = $this->getServiceContext();

            $this->saveToolStates();

            if (!$this->getRunnerService()->isTerminated($serviceContext)) {
                $this->endItemTimer($this->getTime());
                $this->saveItemState();
            }
            $this->initServiceContext();

            $this->saveItemResponses(false);

            if ($this->getRequestParameter('offline') === true) {
                $this->setOffline();
            }

            $serviceContext->getTestSession()->initItemTimer($this->getTime());
            $result = $this->getRunnerService()->move($serviceContext, $direction, $scope, $ref);

            $response = [
                'success' => $result,
            ];

            if ($result) {
                $response['testContext'] = $this->getRunnerService()->getTestContext($serviceContext);

                if ($serviceContext->containsAdaptive()) {
                    // Force map update.
                    $response['testMap'] = $this->getRunnerService()->getTestMap($serviceContext, true);
                }
            }

            common_Logger::d('Test session state : ' . $serviceContext->getTestSession()->getState());

            if ($start === true) {
                // start the timer only when move starts the item session
                // and after context build to avoid timing error
                $this->getRunnerService()->startTimer($serviceContext, $this->getTime());
            }
        } catch (Exception $e) {
            common_Logger::e($e->getMessage());
            $response = $this->getErrorResponse($e);
        }

        return $response;
    }