
import { decodeBase64 } from './buffer.js';

const WELL_KNOWN_ROUTE = '/.well-known';
const AUTH_SERVER_METADATA_DISCOVERY_PATH = `${WELL_KNOWN_ROUTE}/oauth-authorization-server`;
function isAuthorizationProtectedResourceMetadata(obj) {
    if (typeof obj !== 'object' || obj === null) {
        return false;
    }
    const metadata = obj;
    return metadata.resource !== undefined;
}
function isAuthorizationServerMetadata(obj) {
    if (typeof obj !== 'object' || obj === null) {
        return false;
    }
    const metadata = obj;
    return metadata.issuer !== undefined;
}
function isAuthorizationDynamicClientRegistrationResponse(obj) {
    if (typeof obj !== 'object' || obj === null) {
        return false;
    }
    const response = obj;
    return response.client_id !== undefined;
}
function isAuthorizationTokenResponse(obj) {
    if (typeof obj !== 'object' || obj === null) {
        return false;
    }
    const response = obj;
    return response.access_token !== undefined && response.token_type !== undefined;
}
function getDefaultMetadataForUrl(authorizationServer) {
    return {
        issuer: ( authorizationServer.toString()),
        authorization_endpoint: ( ( new URL('/authorize', authorizationServer)).toString()),
        token_endpoint: ( ( new URL('/token', authorizationServer)).toString()),
        registration_endpoint: ( ( new URL('/register', authorizationServer)).toString()),
        response_types_supported: ['code', 'id_token', 'id_token token'],
    };
}
function getMetadataWithDefaultValues(metadata) {
    const issuer = ( new URL(metadata.issuer));
    return {
        ...metadata,
        authorization_endpoint: metadata.authorization_endpoint ?? ( ( new URL('/authorize', issuer)).toString()),
        token_endpoint: metadata.token_endpoint ?? ( ( new URL('/token', issuer)).toString()),
        registration_endpoint: metadata.registration_endpoint ?? ( ( new URL('/register', issuer)).toString()),
    };
}
const DEFAULT_AUTH_FLOW_PORT = 33418;
async function fetchDynamicRegistration(registrationEndpoint, clientName) {
    const response = await fetch(registrationEndpoint, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            client_name: clientName,
            client_uri: 'https://code.visualstudio.com',
            grant_types: ['authorization_code', 'refresh_token', 'urn:ietf:params:oauth:grant-type:device_code'],
            response_types: ['code'],
            redirect_uris: [
                'https://insiders.vscode.dev/redirect',
                'https://vscode.dev/redirect',
                'http://localhost/',
                'http://127.0.0.1/',
                `http://localhost:${DEFAULT_AUTH_FLOW_PORT}/`,
                `http://127.0.0.1:${DEFAULT_AUTH_FLOW_PORT}/`
            ],
            token_endpoint_auth_method: 'none'
        })
    });
    if (!response.ok) {
        throw ( new Error(`Registration failed: ${response.statusText}`));
    }
    const registration = await response.json();
    if (isAuthorizationDynamicClientRegistrationResponse(registration)) {
        return registration;
    }
    throw ( new Error(
        `Invalid authorization dynamic client registration response: ${JSON.stringify(registration)}`
    ));
}
function parseWWWAuthenticateHeader(wwwAuthenticateHeaderValue) {
    const parts = wwwAuthenticateHeaderValue.split(' ');
    const scheme = parts[0];
    const params = {};
    if (parts.length > 1) {
        const attributes = parts.slice(1).join(' ').split(',');
        attributes.forEach(attr => {
            const [key, value] = ( attr.split('=').map(s => s.trim().replace(/"/g, '')));
            params[key] = value;
        });
    }
    return { scheme, params };
}
function getClaimsFromJWT(token) {
    const parts = token.split('.');
    if (parts.length !== 3) {
        throw ( new Error('Invalid JWT token format: token must have three parts separated by dots'));
    }
    const [header, payload, _signature] = parts;
    try {
        const decodedHeader = JSON.parse(( decodeBase64(header).toString()));
        if (typeof decodedHeader !== 'object') {
            throw ( new Error('Invalid JWT token format: header is not a JSON object'));
        }
        const decodedPayload = JSON.parse(( decodeBase64(payload).toString()));
        if (typeof decodedPayload !== 'object') {
            throw ( new Error('Invalid JWT token format: payload is not a JSON object'));
        }
        return decodedPayload;
    }
    catch (e) {
        if (e instanceof Error) {
            throw ( new Error(`Failed to parse JWT token: ${e.message}`));
        }
        throw ( new Error('Failed to parse JWT token'));
    }
}

export { AUTH_SERVER_METADATA_DISCOVERY_PATH, DEFAULT_AUTH_FLOW_PORT, fetchDynamicRegistration, getClaimsFromJWT, getDefaultMetadataForUrl, getMetadataWithDefaultValues, isAuthorizationDynamicClientRegistrationResponse, isAuthorizationProtectedResourceMetadata, isAuthorizationServerMetadata, isAuthorizationTokenResponse, parseWWWAuthenticateHeader };
