class MermaidQueryFormatter {

    public static String format(InsituQuery query) {
        List<String> queryParams= new ArrayList<>();

        if(query.lonMin() != null) {
            queryParams.add(PARAM_LON_MIN + "=" + query.lonMin());
        }
        if(query.latMin() != null) {
            queryParams.add(PARAM_LAT_MIN + "=" + query.latMin());
        }
        if(query.lonMax() != null) {
            queryParams.add(PARAM_LON_MAX + query.lonMax());
        }
        if(query.latMax() != null) {
            queryParams.add(PARAM_LAT_MAX + "=" + query.latMax());
        }
        if(query.startDate() != null) {
            try {
                queryParams.add(PARAM_START_DATE + "=" + URLEncoder.encode(DATE_FORMAT.format(query.startDate()), "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                throw new IllegalArgumentException("start date could not be encoded", e);
            }
        }
        if(query.stopDate() != null) {
            try {
                queryParams.add(PARAM_STOP_DATE + "=" + URLEncoder.encode(DATE_FORMAT.format(query.stopDate()), "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                throw new IllegalArgumentException("stop date could not be encoded", e);
            }
        }
        if(query.param() != null && query.param().length > 0) {
            queryParams.add(PARAM_PARAM + "=" + StringUtils.arrayToCsv(query.param()));
        }
        if(query.datasets() != null && query.datasets().length > 0) {
            queryParams.add(PARAM_CAMPAIGN + "=" + StringUtils.arrayToCsv(query.datasets()));
        }
        if(query.shift() > 0) {
            queryParams.add(PARAM_SHIFT + "=" + query.shift());
        }
        if(query.limit() > 0) {
            queryParams.add(PARAM_LIMIT + "=" + query.limit());
        }
        if(query.countOnly()) {
            queryParams.add(PARAM_COUNT_ONLY);
        }

        if(query.subject() == null) {
            throw new IllegalArgumentException("subject must be specified");
        }
        final StringBuilder sb = new StringBuilder();
        sb.append("/");
        switch (query.subject()) {
            case DATASETS:
                sb.append(CAMPAIGNS_SUBJECT);
                break;
            case PARAMETERS:
                sb.append(PARAMETERS_SUBJECT);
                break;
            case OBSERVATIONS:
                sb.append(OBSERVATIONS_SUBJECT);
                break;
        }
        sb.append("?");

        for (int i = 0; i < queryParams.size(); i++) {
            String queryParam = queryParams.get(i);
            sb.append(queryParam);
            if(i < queryParams.size()-1) {
                sb.append("&");
            }
        }

        return sb.toString();
    }

}