private function parseFilterLink(): self
    {
        if (array_key_exists(static::PARAM_FILTER, $this->getParameters()) === false) {
            $this->setFiltersWithAnd()->setFilterParameters([]);

            return $this;
        }

        $filterSection = $this->getParameters()[static::PARAM_FILTER];
        if (is_array($filterSection) === false || empty($filterSection) === true) {
            throw new InvalidQueryParametersException($this->createParameterError(
                static::PARAM_FILTER,
                $this->getInvalidParamMessage()
            ));
        }

        $isWithAnd = true;
        reset($filterSection);

        // check if top level element is `AND` or `OR`
        $firstKey   = key($filterSection);
        $firstLcKey = strtolower(trim($firstKey));
        if (($hasOr = ($firstLcKey === 'or')) || $firstLcKey === 'and') {
            if (count($filterSection) > 1 ||
                empty($filterSection = $filterSection[$firstKey]) === true ||
                is_array($filterSection) === false
            ) {
                throw new InvalidQueryParametersException($this->createParameterError(
                    static::PARAM_FILTER,
                    $this->getInvalidParamMessage()
                ));
            } else {
                $this->setFilterParameters($filterSection);
                if ($hasOr === true) {
                    $isWithAnd = false;
                }
            }
        } else {
            $this->setFilterParameters($filterSection);
        }

        $isWithAnd === true ? $this->setFiltersWithAnd() : $this->setFiltersWithOr();

        return $this;
    }