import { isRecord } from '@takeshape/util';
import isArray from 'lodash/isArray.js';
import isPlainObject from 'lodash/isPlainObject.js';
import isString from 'lodash/isString.js';
import { latestSchemaJson } from "../schemas/index.js";
/** Resolver Type Utils **/
/**
 * Only tests that the shape is right, not that the name is correct. That's a job for the validator.
 */
export function isBasicResolver(resolver) {
    return isString(resolver?.name) && isString(resolver.service);
}
export function isComposeResolver(resolver) {
    return Boolean(isArray(resolver?.compose) &&
        resolver.compose.length &&
        resolver.compose.every(isBasicResolver));
}
const { definitions: { takeshapeResolver, utilResolver, graphqlResolver, restResolver, awsLambdaResolver } } = latestSchemaJson;
export function isTakeshapeResolver(resolver) {
    return takeshapeResolver.properties.name.enum.includes(resolver.name);
}
export function isGraphqlResolver(resolver) {
    return graphqlResolver.properties.name.enum.includes(resolver.name);
}
export function isRestResolver(resolver) {
    return restResolver.properties.name.enum.includes(resolver.name);
}
export function isAwsLambdaResolver(resolver) {
    return awsLambdaResolver.properties.name.enum.includes(resolver.name);
}
export function isUtilResolver(resolver) {
    return utilResolver.properties.name.enum.includes(resolver.name);
}
/** Directive Mapping Utils **/
/**
 * Determine whether the ambiguous Directive structure is a DirectiveMappingMap
 */
export function isDirectiveMappingMap(maybeMap) {
    return isPlainObject(maybeMap) && Object.keys(maybeMap).length > 0;
}
/**
 * Determine whether the ambiguous Directive structure is a DirectiveMappingArray
 */
export function isDirectiveMappingArray(maybeArray) {
    return isArray(maybeArray) && isArray(maybeArray[0]) && isString(maybeArray[0][0]) && isArray(maybeArray[0][1]);
}
/**
 * Determine whether the ambiguous Directive structure is a DirectiveConfig array
 */
export function isDirectiveConfig(maybeConfig) {
    return isArray(maybeConfig) && isArray(maybeConfig[0]) && isString(maybeConfig[0][0]) && isRecord(maybeConfig[0][1]);
}
/**
 * Determine whether a ParameterSerializeOption is a content type serializer
 */
export function isParameterSerializeContentOptions(maybeContent) {
    return Boolean('contentType' in maybeContent && maybeContent.contentType);
}
/**
 * Determine whether an unknown variable is a `ParameterOp`
 */
export function isParameterOp(maybeOp) {
    const op = maybeOp;
    if (!op.path) {
        return false;
    }
    return isParameterOpNested(op) || isParameterOpMapping(op) || isParameterOpValue(op) || isParameterOpOp(op);
}
/**
 * Determine whether a `ParameterOp` is a `ParameterOpNested`
 */
export function isParameterOpNested(maybeOp) {
    return Boolean('ops' in maybeOp && maybeOp.ops);
}
/**
 * Determine whether a `ParameterOp` is a `ParameterOpMapping`
 */
export function isParameterOpMapping(maybeOp) {
    return Boolean('mapping' in maybeOp && maybeOp.mapping);
}
/**
 * Determine whether a `ParameterOp` is a `ParameterOpMapping`
 */
export function isParameterOpValue(maybeOp) {
    return Boolean('value' in maybeOp && maybeOp.value);
}
/**
 * Determine whether a `ParameterOp` is a `ParameterOpOp`
 */
export function isParameterOpOp(maybeOp) {
    const op = maybeOp;
    if (!op.op) {
        return false;
    }
    return !(isParameterOpNested(op) || isParameterOpMapping(op) || isParameterOpValue(op));
}
/**
 * Determine whether a ParameterSerializeOption is a style serializer
 */
export function isParameterSerializeStyleOptions(maybeStyle) {
    return Boolean('style' in maybeStyle && maybeStyle.style);
}
/** Typeguards for different types of shape schemas **/
export function isRefSchema(maybeRefSchema) {
    return isString(maybeRefSchema['@ref']) || isString(maybeRefSchema.$ref);
}
export function isAllOfSchema(schema) {
    return isArray(schema.allOf);
}
export function isOneOfSchema(schema) {
    return isArray(schema.oneOf);
}
export function isArraySchema(schema) {
    return schema.type === 'array' && isRecord(schema.items);
}
export function isObjectSchema(schema) {
    return schema.type === 'object' && isRecord(schema.properties);
}
