
import { URI } from '../../../../base/common/uri.js';
import { localize2, localize } from '../../../../nls.js';
import { IProductService } from '../../../../platform/product/common/productService.service.js';
import { StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';
import { IStorageService } from '../../../../platform/storage/common/storage.service.js';
import { IEditorService } from '../../../services/editor/common/editorService.service.js';
import { IBrowserWorkbenchEnvironmentService } from '../../../services/environment/browser/environmentService.service.js';
import { isCodeEditor } from '../../../../editor/browser/editorBrowser.js';
import { isEqual } from '../../../../base/common/resources.js';
import { createScanner, SyntaxKind } from '../../../../base/common/json.js';

const TRUSTED_DOMAINS_URI = ( URI.parse("trustedDomains:/Trusted Domains"));
const TRUSTED_DOMAINS_STORAGE_KEY = "http.linkProtectionTrustedDomains";
const TRUSTED_DOMAINS_CONTENT_STORAGE_KEY = "http.linkProtectionTrustedDomainsContent";
async function openInEditor(editorService, resource) {
    await editorService.openEditor({
        resource,
        languageId: "jsonc",
        options: {
            pinned: true
        }
    });
    const editor = editorService.activeTextEditorControl;
    if (!isCodeEditor(editor)) {
        return;
    }
    const model = editor.getModel();
    if (!model || !isEqual(model.uri, resource)) {
        return;
    }
    const scanner = createScanner(model.getValue(), true);
    let offset;
    for (let token = scanner.scan(); token !== SyntaxKind.EOF; token = scanner.scan()) {
        if (token === SyntaxKind.OpenBracketToken) {
            offset = scanner.getTokenOffset() + scanner.getTokenLength();
            const nextToken = scanner.scan();
            if (nextToken !== SyntaxKind.EOF && nextToken !== SyntaxKind.CloseBracketToken) {
                offset = scanner.getTokenOffset();
            }
            break;
        }
    }
    if (offset !== undefined) {
        const position = model.getPositionAt(offset);
        editor.setPosition(position);
        editor.revealPositionInCenter(position);
    }
}
const manageTrustedDomainSettingsCommand = {
    id: "workbench.action.manageTrustedDomain",
    description: {
        description: ( localize2(14851, "Manage Trusted Domains")),
        args: []
    },
    handler: async accessor => {
        const editorService = accessor.get(IEditorService);
        await openInEditor(editorService, TRUSTED_DOMAINS_URI);
        return;
    }
};
async function configureOpenerTrustedDomainsHandler(
    trustedDomains,
    domainToConfigure,
    resource,
    quickInputService,
    storageService,
    editorService,
    telemetryService
) {
    const parsedDomainToConfigure = ( URI.parse(domainToConfigure));
    const toplevelDomainSegements = parsedDomainToConfigure.authority.split(".");
    const domainEnd = toplevelDomainSegements.slice(toplevelDomainSegements.length - 2).join(".");
    const topLevelDomain = "*." + domainEnd;
    const options = [];
    options.push({
        type: "item",
        label: ( localize(14852, "Trust {0}", domainToConfigure)),
        id: "trust",
        toTrust: domainToConfigure,
        picked: true
    });
    const isIP = toplevelDomainSegements.length === 4 && toplevelDomainSegements.every(
        segment => Number.isInteger(+segment) || Number.isInteger(+segment.split(":")[0])
    );
    if (isIP) {
        if (parsedDomainToConfigure.authority.includes(":")) {
            const base = parsedDomainToConfigure.authority.split(":")[0];
            options.push({
                type: "item",
                label: ( localize(14853, "Trust {0} on all ports", base)),
                toTrust: base + ":*",
                id: "trust"
            });
        }
    } else {
        options.push({
            type: "item",
            label: ( localize(14854, "Trust {0} and all its subdomains", domainEnd)),
            toTrust: topLevelDomain,
            id: "trust"
        });
    }
    options.push({
        type: "item",
        label: ( localize(14855, "Trust all domains (disables link protection)")),
        toTrust: "*",
        id: "trust"
    });
    options.push({
        type: "item",
        label: ( localize(14856, "Manage Trusted Domains")),
        id: "manage"
    });
    const pickedResult = await quickInputService.pick(options, {
        activeItem: options[0]
    });
    if (pickedResult && pickedResult.id) {
        switch (pickedResult.id) {
        case "manage":
            {
                const uriWithFragment = TRUSTED_DOMAINS_URI.with({
                    fragment: ( resource.toString())
                });
                await openInEditor(editorService, uriWithFragment);
                return trustedDomains;
            }
        case "trust":
            {
                const itemToTrust = pickedResult.toTrust;
                if (trustedDomains.indexOf(itemToTrust) === -1) {
                    storageService.remove(TRUSTED_DOMAINS_CONTENT_STORAGE_KEY, StorageScope.APPLICATION);
                    storageService.store(
                        TRUSTED_DOMAINS_STORAGE_KEY,
                        JSON.stringify([...trustedDomains, itemToTrust]),
                        StorageScope.APPLICATION,
                        StorageTarget.USER
                    );
                    return [...trustedDomains, itemToTrust];
                }
            }
        }
    }
    return [];
}
async function readTrustedDomains(accessor) {
    const {
        defaultTrustedDomains,
        trustedDomains
    } = readStaticTrustedDomains(accessor);
    return {
        defaultTrustedDomains,
        trustedDomains
    };
}
function readStaticTrustedDomains(accessor) {
    const storageService = accessor.get(IStorageService);
    const productService = accessor.get(IProductService);
    const environmentService = accessor.get(IBrowserWorkbenchEnvironmentService);
    const defaultTrustedDomains = [
        ...(productService.linkProtectionTrustedDomains ?? []),
        ...(environmentService.options?.additionalTrustedDomains ?? [])
    ];
    let trustedDomains = [];
    try {
        const trustedDomainsSrc = storageService.get(TRUSTED_DOMAINS_STORAGE_KEY, StorageScope.APPLICATION);
        if (trustedDomainsSrc) {
            trustedDomains = JSON.parse(trustedDomainsSrc);
        }
    } catch (err) {}
    return {
        defaultTrustedDomains,
        trustedDomains
    };
}

export { TRUSTED_DOMAINS_CONTENT_STORAGE_KEY, TRUSTED_DOMAINS_STORAGE_KEY, configureOpenerTrustedDomainsHandler, manageTrustedDomainSettingsCommand, readStaticTrustedDomains, readTrustedDomains };
