"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.Pick = Pick;
const type_1 = require("../create/type");
const discard_1 = require("../discard/discard");
const index_1 = require("../computed/index");
const index_2 = require("../intersect/index");
const index_3 = require("../literal/index");
const index_4 = require("../object/index");
const index_5 = require("../union/index");
const index_6 = require("../indexed/index");
const symbols_1 = require("../symbols/symbols");
// ------------------------------------------------------------------
// Guards
// ------------------------------------------------------------------
const kind_1 = require("../guard/kind");
const value_1 = require("../guard/value");
// ------------------------------------------------------------------
// Infrastructure
// ------------------------------------------------------------------
const pick_from_mapped_key_1 = require("./pick-from-mapped-key");
const pick_from_mapped_result_1 = require("./pick-from-mapped-result");
function FromIntersect(types, propertyKeys) {
    return types.map((type) => PickResolve(type, propertyKeys));
}
// prettier-ignore
function FromUnion(types, propertyKeys) {
    return types.map((type) => PickResolve(type, propertyKeys));
}
// prettier-ignore
function FromProperties(properties, propertyKeys) {
    const result = {};
    for (const K2 of propertyKeys)
        if (K2 in properties)
            result[K2] = properties[K2];
    return result;
}
// prettier-ignore
function FromObject(Type, keys, properties) {
    const options = (0, discard_1.Discard)(Type, [symbols_1.TransformKind, '$id', 'required', 'properties']);
    const mappedProperties = FromProperties(properties, keys);
    return (0, index_4.Object)(mappedProperties, options);
}
// prettier-ignore
function UnionFromPropertyKeys(propertyKeys) {
    const result = propertyKeys.reduce((result, key) => (0, kind_1.IsLiteralValue)(key) ? [...result, (0, index_3.Literal)(key)] : result, []);
    return (0, index_5.Union)(result);
}
// prettier-ignore
function PickResolve(type, propertyKeys) {
    return ((0, kind_1.IsIntersect)(type) ? (0, index_2.Intersect)(FromIntersect(type.allOf, propertyKeys)) :
        (0, kind_1.IsUnion)(type) ? (0, index_5.Union)(FromUnion(type.anyOf, propertyKeys)) :
            (0, kind_1.IsObject)(type) ? FromObject(type, propertyKeys, type.properties) :
                (0, index_4.Object)({}));
}
/** `[Json]` Constructs a type whose keys are picked from the given type */
// prettier-ignore
function Pick(type, key, options) {
    const typeKey = (0, value_1.IsArray)(key) ? UnionFromPropertyKeys(key) : key;
    const propertyKeys = (0, kind_1.IsSchema)(key) ? (0, index_6.IndexPropertyKeys)(key) : key;
    const isTypeRef = (0, kind_1.IsRef)(type);
    const isKeyRef = (0, kind_1.IsRef)(key);
    return ((0, kind_1.IsMappedResult)(type) ? (0, pick_from_mapped_result_1.PickFromMappedResult)(type, propertyKeys, options) :
        (0, kind_1.IsMappedKey)(key) ? (0, pick_from_mapped_key_1.PickFromMappedKey)(type, key, options) :
            (isTypeRef && isKeyRef) ? (0, index_1.Computed)('Pick', [type, typeKey], options) :
                (!isTypeRef && isKeyRef) ? (0, index_1.Computed)('Pick', [type, typeKey], options) :
                    (isTypeRef && !isKeyRef) ? (0, index_1.Computed)('Pick', [type, typeKey], options) :
                        (0, type_1.CreateType)({ ...PickResolve(type, propertyKeys), ...options }));
}
