class BasicPath implements Path {

    @Override
    public String toString() {
        if (describedBy.isPresent() && !describedBy.equals(xpathExplanation)) {
            return describedBy.get();
        } else {
            Optional<String> underlyingOption = (underlying.isPresent()) ?
                    Optional.of("under reference element " + underlying.get()) :
                    Optional.empty();
            Optional<String> xpathOption = getXpathExplanationForToString();

            Optional<String> propsOption =
                    (elementProperties.size() == 1 && (!xpathOption.orElse("").contains(", ") || xpathOption.equals(describedBy))) ?
                            getPropertiesToStringForLength1() :
                            (elementProperties.size() == 2 && !xpathOption.orElse("").contains(" ")) ?
                                    Optional.of(format("that %s, and %s",
                                            elementProperties.get(0), elementProperties.get(elementProperties.size() - 1))) :
                                    (elementProperties.size() > 1 || (xpathOption.orElse("").contains(" ") && !elementProperties.isEmpty())) ?
                                            getPropertiesToStringForLengthLargerThan2() :
                                            Optional.empty();

            return (xpathExplanation.isPresent() && !underlyingOption.isPresent() && !propsOption.isPresent()) ?
                    xpathExplanation.get() :
                    Stream.of(underlyingOption, xpathOption, propsOption).filter(Optional::isPresent).map(Optional::get).
                            collect(Collectors.joining(", "));
        }

    }

    private  BasicPath(Optional<WebElement> underlying,
                      Optional<String> xpath,
                      List<ElementProperty> elementProperties,
                      Optional<String> xpathExplanation,
                      Optional<String> describedBy,
                      Optional<String> insideXpath,
                      Optional<String> alternateXpath
    );

}