import { CreateType } from '../create/type.mjs';
import { Kind, Hint } from '../symbols/index.mjs';
import { Never } from '../never/index.mjs';
import { Number } from '../number/index.mjs';
import { Object } from '../object/index.mjs';
import { String } from '../string/index.mjs';
import { Union } from '../union/index.mjs';
import { IsTemplateLiteralFinite } from '../template-literal/index.mjs';
import { PatternStringExact, PatternNumberExact, PatternNeverExact } from '../patterns/index.mjs';
import { IndexPropertyKeys } from '../indexed/index.mjs';
// ------------------------------------------------------------------
// ValueGuard
// ------------------------------------------------------------------
import { IsUndefined } from '../guard/value.mjs';
// ------------------------------------------------------------------
// TypeGuard
// ------------------------------------------------------------------
import { IsInteger, IsLiteral, IsAny, IsBoolean, IsNever, IsNumber, IsString, IsRegExp, IsTemplateLiteral, IsUnion } from '../guard/kind.mjs';
// ------------------------------------------------------------------
// RecordCreateFromPattern
// ------------------------------------------------------------------
// prettier-ignore
function RecordCreateFromPattern(pattern, T, options) {
    return CreateType({ [Kind]: 'Record', type: 'object', patternProperties: { [pattern]: T } }, options);
}
// ------------------------------------------------------------------
// RecordCreateFromKeys
// ------------------------------------------------------------------
// prettier-ignore
function RecordCreateFromKeys(K, T, options) {
    const result = {};
    for (const K2 of K)
        result[K2] = T;
    return Object(result, { ...options, [Hint]: 'Record' });
}
// prettier-ignore
function FromTemplateLiteralKey(K, T, options) {
    return (IsTemplateLiteralFinite(K)
        ? RecordCreateFromKeys(IndexPropertyKeys(K), T, options)
        : RecordCreateFromPattern(K.pattern, T, options));
}
// prettier-ignore
function FromUnionKey(key, type, options) {
    return RecordCreateFromKeys(IndexPropertyKeys(Union(key)), type, options);
}
// prettier-ignore
function FromLiteralKey(key, type, options) {
    return RecordCreateFromKeys([key.toString()], type, options);
}
// prettier-ignore
function FromRegExpKey(key, type, options) {
    return RecordCreateFromPattern(key.source, type, options);
}
// prettier-ignore
function FromStringKey(key, type, options) {
    const pattern = IsUndefined(key.pattern) ? PatternStringExact : key.pattern;
    return RecordCreateFromPattern(pattern, type, options);
}
// prettier-ignore
function FromAnyKey(_, type, options) {
    return RecordCreateFromPattern(PatternStringExact, type, options);
}
// prettier-ignore
function FromNeverKey(_key, type, options) {
    return RecordCreateFromPattern(PatternNeverExact, type, options);
}
// prettier-ignore
function FromBooleanKey(_key, type, options) {
    return Object({ true: type, false: type }, options);
}
// prettier-ignore
function FromIntegerKey(_key, type, options) {
    return RecordCreateFromPattern(PatternNumberExact, type, options);
}
// prettier-ignore
function FromNumberKey(_, type, options) {
    return RecordCreateFromPattern(PatternNumberExact, type, options);
}
// ------------------------------------------------------------------
// TRecordOrObject
// ------------------------------------------------------------------
/** `[Json]` Creates a Record type */
export function Record(key, type, options = {}) {
    // prettier-ignore
    return (IsUnion(key) ? FromUnionKey(key.anyOf, type, options) :
        IsTemplateLiteral(key) ? FromTemplateLiteralKey(key, type, options) :
            IsLiteral(key) ? FromLiteralKey(key.const, type, options) :
                IsBoolean(key) ? FromBooleanKey(key, type, options) :
                    IsInteger(key) ? FromIntegerKey(key, type, options) :
                        IsNumber(key) ? FromNumberKey(key, type, options) :
                            IsRegExp(key) ? FromRegExpKey(key, type, options) :
                                IsString(key) ? FromStringKey(key, type, options) :
                                    IsAny(key) ? FromAnyKey(key, type, options) :
                                        IsNever(key) ? FromNeverKey(key, type, options) :
                                            Never(options));
}
// ------------------------------------------------------------------
// Record Utilities
// ------------------------------------------------------------------
/** Gets the Records Pattern */
export function RecordPattern(record) {
    return globalThis.Object.getOwnPropertyNames(record.patternProperties)[0];
}
/** Gets the Records Key Type */
// prettier-ignore
export function RecordKey(type) {
    const pattern = RecordPattern(type);
    return (pattern === PatternStringExact ? String() :
        pattern === PatternNumberExact ? Number() :
            String({ pattern }));
}
/** Gets a Record Value Type */
// prettier-ignore
export function RecordValue(type) {
    return type.patternProperties[RecordPattern(type)];
}
