public static PathWrapper createPathWrapper(
      JSONObject path, boolean tmpCalcPoints, boolean tmpInstructions, boolean tmpElevation) {
    PathWrapper pathWrapper = new PathWrapper();
    pathWrapper.addErrors(readErrors(path));
    if (pathWrapper.hasErrors()) return pathWrapper;

    if (path.has("snapped_waypoints")) {
      String snappedPointStr = path.getString("snapped_waypoints");
      PointList snappedPoints = WebHelper.decodePolyline(snappedPointStr, 5, tmpElevation);
      pathWrapper.setWaypoints(snappedPoints);
    }

    if (tmpCalcPoints) {
      String pointStr = path.getString("points");
      PointList pointList = WebHelper.decodePolyline(pointStr, 100, tmpElevation);
      pathWrapper.setPoints(pointList);

      if (tmpInstructions) {
        JSONArray instrArr = path.getJSONArray("instructions");

        InstructionList il = new InstructionList(null);
        int viaCount = 1;
        for (int instrIndex = 0; instrIndex < instrArr.length(); instrIndex++) {
          JSONObject jsonObj = instrArr.getJSONObject(instrIndex);
          double instDist = jsonObj.getDouble("distance");
          String text = jsonObj.getString("text");
          long instTime = jsonObj.getLong("time");
          int sign = jsonObj.getInt("sign");
          JSONArray iv = jsonObj.getJSONArray("interval");
          int from = iv.getInt(0);
          int to = iv.getInt(1);
          PointList instPL = new PointList(to - from, tmpElevation);
          for (int j = from; j <= to; j++) {
            instPL.add(pointList, j);
          }

          InstructionAnnotation ia = InstructionAnnotation.EMPTY;
          if (jsonObj.has("annotation_importance") && jsonObj.has("annotation_text")) {
            ia =
                new InstructionAnnotation(
                    jsonObj.getInt("annotation_importance"),
                    jsonObj.getString("annotation_text"),
                    0,
                    false);
          }

          Instruction instr;
          if (sign == Instruction.USE_ROUNDABOUT || sign == Instruction.LEAVE_ROUNDABOUT) {
            RoundaboutInstruction ri = new RoundaboutInstruction(sign, text, ia, instPL);

            if (jsonObj.has("exit_number")) {
              ri.setExitNumber(jsonObj.getInt("exit_number"));
            }

            if (jsonObj.has("turn_angle")) {
              // TODO provide setTurnAngle setter
              double angle = jsonObj.getDouble("turn_angle");
              ri.setDirOfRotation(angle);
              ri.setRadian((angle < 0 ? -Math.PI : Math.PI) - angle);
            }

            instr = ri;
          } else if (sign == Instruction.REACHED_VIA) {
            ViaInstruction tmpInstr = new ViaInstruction(text, ia, instPL);
            tmpInstr.setViaCount(viaCount);
            viaCount++;
            instr = tmpInstr;
          } else if (sign == Instruction.FINISH) {
            instr = new FinishInstruction(instPL, 0);
          } else {
            instr = new Instruction(sign, text, ia, instPL);
          }

          // The translation is done from the routing service so just use the provided string
          // instead of creating a combination with sign and name etc
          instr.setUseRawName();

          instr.setDistance(instDist).setTime(instTime);
          il.add(instr);
        }
        pathWrapper.setInstructions(il);
      }
    }

    double distance = path.getDouble("distance");
    long time = path.getLong("time");
    pathWrapper.setDistance(distance).setTime(time);
    return pathWrapper;
  }