import { format } from 'util';
import { CodeBuilder } from '../../helpers/code-builder.js';
import { HTTPSnippet } from '../../index.js';
import { Lang } from '../../helpers/constants.js';
import { buildUrlExpression, printUrlVariablesDeclarations } from '../../helpers/code-helpers.js';
import { startCase } from '../../helpers/lodash-int.js';
import { normalizeMimeType } from '../../../../utils.js';
import { MediaTypes } from '../../../../../constants.js';
import { objectToPhpArray } from './utils.js';
function getVariableName(name, prefix) {
    return prefix ? `$${prefix}${startCase(name)}` : `$${name}`;
}
const handler = function (source, originalOptions, { target, client }) {
    const options = {
        showBoilerplate: true,
        checkErrors: false,
        printBody: true,
        indent: '  ',
        noTags: true,
        shortTags: false,
        maxRedirects: 10,
        namedErrors: false,
        closingTag: false,
        ...originalOptions,
    };
    let postData;
    let isPayloadVariable = false;
    const code = new CodeBuilder({
        indentation: options.indent,
        capitalize: true,
        lang: Lang.PHP,
    });
    const securityOAuth2ExtraCalls = source.securityOAuth2ExtraCalls?.[0];
    const curlVariableName = getVariableName('curl', options.variablesPrefix);
    const responseVariableName = getVariableName('response', options.variablesPrefix);
    const errorVariableName = getVariableName('error', options.variablesPrefix);
    if (!options.noTags) {
        code.push(options.shortTags ? '<?' : '<?php').blank();
    }
    if (securityOAuth2ExtraCalls) {
        const variablesPrefix = 'oAuth2';
        const oAuth2PrefixCode = new HTTPSnippet(securityOAuth2ExtraCalls).convert(target, client, {
            ...options,
            showBoilerplate: false,
            variablesPrefix,
        });
        code.push(oAuth2PrefixCode);
        code.blank();
        source.allHeaders.Authorization = `Bearer " . ${getVariableName('response', variablesPrefix)}.access_token`;
    }
    const headers = Object.keys(source.headersObj)
        .sort()
        .map(function (key) {
        if (key === 'Authorization' && securityOAuth2ExtraCalls) {
            return format('"%s: %s', key, source.allHeaders.Authorization);
        }
        return format('"%s: %s"', key, source.headersObj[key]);
    });
    if (source.basicAuth) {
        const { username, password } = source.basicAuth;
        headers.push(`"Authorization: Basic " . base64_encode("${username}:${password}")`);
    }
    if (options.showBoilerplate) {
        code.push('/**').push(' * Requires libcurl').push(' */').blank();
    }
    printUrlVariablesDeclarations(source, code);
    let queryVariableName = '';
    if (Object.keys(source.queryObj || {}).length) {
        const queryCode = objectToPhpArray(source.queryObj || {}, { indent: options.indent });
        queryVariableName = '$query';
        code.push(`${queryVariableName} = ${queryCode};`).blank();
    }
    code.push(`${curlVariableName} = curl_init();`);
    code.blank();
    if (source.postData) {
        switch (normalizeMimeType(source.postData.mimeType)) {
            case MediaTypes.JSON: {
                const array = objectToPhpArray(source.postData.jsonObj || {}, { indent: options.indent });
                isPayloadVariable = true;
                postData = 'json_encode($payload)';
                code.push(`$payload = ${array};`).blank();
                break;
            }
            case MediaTypes.MULTIPART: {
                const payloadData = source.postData.params
                    .map(({ name, value }) => {
                    return `${options.indent}"${name}" => "${value}",\n`;
                })
                    .join('');
                isPayloadVariable = true;
                postData = '$payload';
                code.push(`$payload = array(\n${payloadData});`).blank();
                break;
            }
            case MediaTypes.URL_ENCODED: {
                const payloadForm = source.postData.params
                    .map(({ name, value }) => {
                    return `${name}=${value}`;
                })
                    .join('&');
                isPayloadVariable = true;
                postData = '$payload';
                code.push(`$payload = "${payloadForm}";`).blank();
                break;
            }
            default:
                postData = source.postData.text;
                break;
        }
    }
    let URL = buildUrlExpression(source, code);
    if (queryVariableName) {
        if (URL.endsWith('"')) {
            //URL ends with string. `"https://httpbin.org/" . "?" . variable` should be `"https://httpbin.org/?" . variable`
            URL = URL.slice(0, -1) + `?" . http_build_query(${queryVariableName})`;
        }
        else {
            //URL ends with variable
            URL += ` . "?" . http_build_query(${queryVariableName})`;
        }
    }
    const curlOptions = [
        {
            escape: !isPayloadVariable,
            name: 'CURLOPT_POSTFIELDS',
            value: postData,
        },
        {
            escape: true,
            name: 'CURLOPT_PORT',
            value: source.uriObj.port,
        },
        {
            escape: false,
            name: 'CURLOPT_URL',
            value: URL,
        },
        {
            escape: false,
            name: 'CURLOPT_RETURNTRANSFER',
            value: 'true',
        },
        {
            escape: true,
            name: 'CURLOPT_CUSTOMREQUEST',
            value: source.method.toUpperCase(),
        },
    ];
    code.push(`curl_setopt_array(${curlVariableName}, [`);
    const curlopts = new CodeBuilder({
        indentation: options.indent,
        lineJoin: `\n${options.indent}`,
        variablesPrefix: options.variablesPrefix,
        capitalize: true,
        lang: Lang.PHP,
    });
    if (headers.length) {
        curlopts
            .push('CURLOPT_HTTPHEADER => [')
            .push(1, headers.join(',\n' + options.indent + options.indent))
            .push('],');
    }
    curlOptions.forEach(function (option) {
        if (![null, undefined, ''].includes(option.value)) {
            curlopts.push(format('%s => %s,', option.name, option.escape ? JSON.stringify(option.value) : option.value));
        }
    });
    const cookies = source.cookies.map(function (cookie) {
        return encodeURIComponent(cookie.name) + '=' + encodeURIComponent(cookie.value);
    });
    if (cookies.length) {
        curlopts.push(format('CURLOPT_COOKIE => "%s",', cookies.join('; ')));
    }
    code
        .push(1, curlopts.join())
        .push(']);')
        .blank()
        .push(`${responseVariableName} = curl_exec(${curlVariableName});`)
        .push(`${errorVariableName} = curl_error(${curlVariableName});`)
        .blank()
        .push(`curl_close(${curlVariableName});`)
        .blank()
        .push(`if (${errorVariableName}) {`);
    if (options.namedErrors) {
        code.push(1, `echo array_flip(get_defined_constants(true)["curl"])[${errorVariableName}];`);
    }
    else {
        code.push(1, `echo "cURL Error #:" . ${errorVariableName};`);
    }
    code.push('} else {').push(1, `echo ${responseVariableName};`).push('}');
    if (!options.noTags && options.closingTag) {
        code.blank().push('?>');
    }
    return code.join();
};
export const info = {
    key: 'curl',
    title: 'cURL',
    link: 'http://php.net/manual/en/book.curl.php',
    description: 'PHP with ext-curl',
};
export default handler;
//# sourceMappingURL=curl.js.map