"use strict";
// -*- mode: typescript; indent-tabs-mode: nil; js-basic-offset: 4 -*-
//
// This file is part of Genie
//
// Copyright 2019 National Taiwan University
//           2020 The Board of Trustees of the Leland Stanford Junior University
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: Giovanni Campagna <gcampagn@cs.stanford.edu>
//         Elvis Yu-Jing Lin <r06922068@ntu.edu.tw> <elvisyjlin@gmail.com>
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.renumberEntities = exports.makeDummyEntities = exports.makeDummyEntity = exports.isHumanEntity = exports.sampleString = exports.tokenizeExample = exports.clean = exports.split = exports.splitParams = exports.cleanKind = void 0;
const assert_1 = __importDefault(require("assert"));
const thingtalk_1 = require("thingtalk");
const random_1 = require("./random");
const entity_utils_1 = require("./entity-utils");
Object.defineProperty(exports, "makeDummyEntity", { enumerable: true, get: function () { return entity_utils_1.makeDummyEntity; } });
Object.defineProperty(exports, "makeDummyEntities", { enumerable: true, get: function () { return entity_utils_1.makeDummyEntities; } });
Object.defineProperty(exports, "renumberEntities", { enumerable: true, get: function () { return entity_utils_1.renumberEntities; } });
class ValidationError extends Error {
    constructor(message) {
        super(message);
        this.code = 'EINVAL';
    }
}
function clean(name) {
    if (/^[vwgp]_/.test(name))
        name = name.substr(2);
    return name.replace(/_/g, ' ').trim().replace(/([^A-Z ])([A-Z])/g, '$1 $2').toLowerCase();
}
exports.clean = clean;
function cleanKind(kind) {
    // thingengine.phone -> phone
    if (kind.startsWith('org.thingpedia.builtin.thingengine.'))
        kind = kind.substr('org.thingpedia.builtin.thingengine.'.length);
    // org.thingpedia.builtin.omlet -> omlet
    if (kind.startsWith('org.thingpedia.builtin.'))
        kind = kind.substr('org.thingpedia.builtin.'.length);
    // org.thingpedia.iot.switch -> switch
    if (kind.startsWith('org.thingpedia.iot.'))
        kind = kind.substr('org.thingpedia.iot.'.length);
    // org.thingpedia.weather -> weather
    if (kind.startsWith('org.thingpedia.'))
        kind = kind.substr('org.thingpedia.'.length);
    // com.xkcd -> xkcd
    if (kind.startsWith('com.'))
        kind = kind.substr('com.'.length);
    if (kind.startsWith('gov.'))
        kind = kind.substr('gov.'.length);
    if (kind.startsWith('org.'))
        kind = kind.substr('org.'.length);
    if (kind.startsWith('uk.co.'))
        kind = kind.substr('uk.co.'.length);
    kind = kind.replace(/[.-]/g, ' ');
    return clean(kind);
}
exports.cleanKind = cleanKind;
const PARAM_REGEX = /\$(?:\$|([a-zA-Z0-9_]+(?![a-zA-Z0-9_]))|{([a-zA-Z0-9_]+)(?::([a-zA-Z0-9_-]+))?})/;
function* split(pattern, regexp) {
    // a split that preserves capturing parenthesis
    const clone = new RegExp(regexp, 'g');
    let match = clone.exec(pattern);
    let i = 0;
    while (match !== null) {
        if (match.index > i)
            yield pattern.substring(i, match.index);
        yield match;
        i = clone.lastIndex;
        match = clone.exec(pattern);
    }
    if (i < pattern.length)
        yield pattern.substring(i, pattern.length);
}
exports.split = split;
function splitParams(utterance) {
    return Array.from(split(utterance, PARAM_REGEX));
}
exports.splitParams = splitParams;
function tokenizeExample(tokenizer, utterance, id) {
    let replaced = '';
    const params = [];
    for (const chunk of splitParams(utterance.trim())) {
        if (chunk === '')
            continue;
        if (typeof chunk === 'string') {
            replaced += chunk;
            continue;
        }
        const [match, param1, param2, opt] = chunk;
        if (match === '$$') {
            replaced += '$';
            continue;
        }
        const param = param1 || param2;
        replaced += ' ____ ';
        params.push([param, opt]);
    }
    const tokenized = tokenizer.tokenize(replaced);
    const tokens = tokenized.tokens;
    const entities = tokenized.entities;
    if (Object.keys(entities).length > 0)
        throw new ValidationError(`Error in Example ${id}: Cannot have entities in the utterance`);
    let preprocessed = '';
    let first = true;
    for (let token of tokens) {
        if (token === '____') {
            const [param, opt] = params.shift();
            if (opt)
                token = '${' + param + ':' + opt + '}';
            else
                token = '${' + param + '}';
        }
        else if (token === '$') {
            token = '$$';
        }
        if (!first)
            preprocessed += ' ';
        preprocessed += token;
        first = false;
    }
    return preprocessed;
}
exports.tokenizeExample = tokenizeExample;
function sampleString(words, langPack, rng) {
    assert_1.default(rng);
    let seq;
    if (words.length > 6) {
        const sampledLengthIdx = random_1.categorical([0.4, 0.4, 0.2, 0.1, 0.05], rng);
        const length = [2, 3, 4, 5, 6][sampledLengthIdx];
        const idx = Math.floor(rng() * (words.length - length));
        seq = words.slice(idx, idx + length);
    }
    else if (words.length > 4) {
        const sampledLengthIdx = random_1.categorical([0.4, 0.4, 0.2], rng);
        const length = [2, 3, 4][sampledLengthIdx];
        const idx = Math.floor(rng() * (words.length - length));
        seq = words.slice(idx, idx + length);
    }
    else if (words.length > 2) {
        const sampledLengthIdx = random_1.categorical([0.5, 0.5], rng);
        const length = [2, 3][sampledLengthIdx];
        const idx = Math.floor(rng() * (words.length - length));
        seq = words.slice(idx, idx + length);
    }
    else {
        seq = words;
    }
    if (seq.some((w) => !langPack.isGoodWord(w)))
        return null;
    const cand = seq.join(' ');
    if (!langPack.isGoodSentence(cand))
        return null;
    return cand;
}
exports.sampleString = sampleString;
function isHumanEntity(type) {
    if (type instanceof thingtalk_1.Type.Entity)
        return isHumanEntity(type.type);
    if (type instanceof thingtalk_1.Type.Array)
        return isHumanEntity(type.elem);
    if (typeof type !== 'string')
        return false;
    if (['tt:contact', 'tt:username', 'org.wikidata:human'].includes(type))
        return true;
    if (type.startsWith('org.schema') && type.endsWith(':Person'))
        return true;
    return false;
}
exports.isHumanEntity = isHumanEntity;
//# sourceMappingURL=misc-utils.js.map