import { CodeBuilder } from '../../helpers/code-builder.js';
import { HTTPSnippet } from '../../index.js';
import { normalizeMimeType } from '../../../../utils.js';
import { addIndentation, buildUrlExpression, printUrlVariablesDeclarations, } from '../../helpers/code-helpers.js';
import { Lang } from '../../helpers/constants.js';
import { MediaTypes } from '../../../../../constants.js';
const hasQueryParams = (source) => !!(source.uriObj.query && Object.keys(source.uriObj.query).length);
const getBody = (source) => source.postData && source.postData.mimeType === MediaTypes.URL_ENCODED
    ? 'HttpRequest.BodyPublishers.ofString(form)'
    : source.postData
        ? 'HttpRequest.BodyPublishers.ofString(payload)'
        : ['POST', 'PUT', 'PATCH'].includes(source.method.toUpperCase())
            ? 'HttpRequest.BodyPublishers.ofString("some body text")'
            : '';
const handler = function (source, originalOptions, { target, client }) {
    const options = Object.assign({ indent: '  ', withWrapper: true }, originalOptions);
    const code = new CodeBuilder({
        indentation: options.indent,
        variablesPrefix: options.variablesPrefix,
        capitalize: true,
        lang: Lang.JAVA,
    });
    if (options.withComments) {
        addComments(code, source);
    }
    if (options.withImports) {
        addImports(code, source);
    }
    if (options.withWrapper) {
        code.push('public class App {');
        code.push(1, 'public static void main(String[] args) throws Exception {');
        code.push(2, 'var httpClient = HttpClient.newBuilder().build();');
        code.blank();
    }
    if (source.securityOAuth2ExtraCalls?.length) {
        const oAuth2PrefixCode = new HTTPSnippet(source.securityOAuth2ExtraCalls?.[0]).convert(target, client, {
            ...options,
            withImports: false,
            withWrapper: false,
            withComments: false,
            variablesPrefix: 'oauth2',
        });
        code.push(oAuth2PrefixCode);
        code.blank();
        code.push(2, 'var oauth2Response = httpClient.send(oauth2Request, HttpResponse.BodyHandlers.ofString());');
        code.push(2, 'var accessToken = new JSONObject(oauth2Response.body()).getString("access_token");');
        code.blank();
    }
    if (source.postData) {
        switch (normalizeMimeType(source.postData.mimeType)) {
            case MediaTypes.URL_ENCODED:
                if (source.postData.params) {
                    code.push(2, 'HashMap<String, String> params = new HashMap<>();');
                    source.postData.params.forEach((param) => {
                        code.push(2, 'params.put("%s", "%s");', param.name, param.value);
                    });
                    code.blank();
                    code.push(2, 'var form = params.keySet().stream()');
                    code.push(3, '.map(key -> key + "=" + URLEncoder.encode(params.get(key), StandardCharsets.UTF_8))');
                    code.push(3, '.collect(Collectors.joining("&"));');
                    code.blank();
                }
                break;
            case MediaTypes.JSON:
                if (source.postData.jsonObj) {
                    code.push(2, `var payload = String.join("\\n"
      ${addIndentation(JSON.stringify(source.postData.jsonObj, null, 1)
                        .replace(/"/g, '\\"')
                        .replace(/^/gm, ', "')
                        .replace(/$/gm, '"'), { level: 3, indent: options.indent, firstLine: false })}`);
                    code.push(2, ');');
                    code.blank();
                }
                break;
            case MediaTypes.XML:
                if (source.postData.text) {
                    code.push(2, 'var payload = String.join("\\n"');
                    source.postData.text
                        .trim()
                        .split('\n')
                        .forEach((item) => {
                        const line = item.replace(/"/g, '\\"');
                        code.push(3, `"${line}", `);
                    });
                    code.push(2, ');');
                    code.blank();
                }
                break;
            case MediaTypes.MULTIPART:
                if (source.postData.params) {
                    code.push(2, 'var multipartBody = MultipartBodyPublisher.newBuilder();');
                    if (source.postData.params) {
                        source.postData.params.forEach((param) => {
                            code.push(2, 'multipartBody.append("%s", "%s");', param.name, param.value);
                        });
                    }
                    code.push(2, 'var body = multipartBody.build();');
                    code.blank();
                }
                break;
        }
    }
    if (hasQueryParams(source)) {
        code.push(2, 'HashMap<String, String> params = new HashMap<>();');
        for (const [key, value] of Object.entries(source.uriObj.query)) {
            code.push(2, 'params.put("%s", "%s");', key, value);
        }
        code.blank();
        code.push(2, 'var query = params.keySet().stream()');
        code.push(3, '.map(key -> key + "=" + URLEncoder.encode(params.get(key), StandardCharsets.UTF_8))');
        code.push(3, '.collect(Collectors.joining("&"));');
        code.blank();
    }
    code.push(2, `var ${code.var('host')} = "%s";`, source.uriObj.protocol + '//' + source.uriObj.host);
    printUrlVariablesDeclarations(source, code, 2);
    const URLSource = { ...source, ...{ pathname: source.uriObj.pathname } };
    code.push(2, `var ${code.var('pathname')} = %s;`, buildUrlExpression(URLSource, code));
    code.push(2, `var ${code.var('request')} = HttpRequest.newBuilder()`);
    if (source.method.toUpperCase() === 'PATCH')
        code.push(3, '.method("PATCH", %s)', getBody(source));
    else
        code.push(3, '.%s(%s)', source.method.toUpperCase(), getBody(source));
    code.push(3, `.uri(URI.create(${code.var('host')} + ${code.var('pathname')} %s))`, hasQueryParams(source) ? "+ '?' + query" : '');
    if (source.securityOAuth2ExtraCalls?.length) {
        source.allHeaders.Authorization = '"Bearer " + accessToken';
    }
    const headers = Object.keys(source.allHeaders);
    if (headers.length) {
        headers.forEach((key) => {
            code.push(3, '.header("%s", %s)', key, key === 'Authorization' && source.securityOAuth2ExtraCalls?.length
                ? source.allHeaders[key] // raw expression, not a string
                : `"${source.allHeaders[key]}"`);
        });
    }
    if (source.basicAuth) {
        const { username, password } = source.basicAuth;
        code.push(3, `.header("Authorization", "Basic " + Base64.getEncoder().encodeToString(("${username}:${password}").getBytes()))`);
    }
    code.push(3, '.build();');
    if (options.withWrapper) {
        code.blank();
        code.push(2, 'var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());');
        code.blank();
        code.push(2, 'System.out.println(response.body());');
        code.push(1, '}');
        code.push('}');
    }
    return code.join();
};
export const info = {
    key: 'httpclient',
    title: 'HttpClient',
    link: 'https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpClient.html',
    description: 'HttpClient (Java SE 11 & JDK 11 )',
};
export default handler;
function addComments(code, source) {
    code.push('/**');
    code.push(' * Requires JDK >= 11');
    if (source.securityOAuth2ExtraCalls?.length) {
        code.push(' *');
        code.push(' * Requires package "org.json" >= 20201115');
        code.push(' * See here for installation details:');
        code.push(' *  https://search.maven.org/artifact/org.json/json');
    }
    code.push(' */');
    code.blank();
}
function addImports(code, source) {
    code.push('import java.net.*;');
    code.push('import java.net.http.*;');
    code.push('import java.util.*;');
    if ((normalizeMimeType(source.postData?.mimeType) === MediaTypes.URL_ENCODED &&
        source.postData?.params) ||
        source.securityOAuth2ExtraCalls?.length ||
        hasQueryParams(source)) {
        code.push('import java.nio.charset.StandardCharsets;');
        code.push('import java.util.stream.Collectors;');
    }
    if (source.securityOAuth2ExtraCalls?.length)
        code.push('import org.json.JSONObject;');
    code.blank();
}
//# sourceMappingURL=httpclient.js.map