import * as M from '../meta';

export type Type =
    | { kind: 'union', variants: VariantMap } // zero: never
    | SimpleType

export type SimpleType = FieldType | RecordType

export type FieldType =
    | { kind: 'unit' }
    | { kind: 'array', type: FieldType }
    | { kind: 'set', type: FieldType }
    | { kind: 'dictionary', key: FieldType, value: FieldType }
    | RefType

export type RefType =
    | { kind: 'ref', typeName: string, ref: M.Ref | null } // ref === null for base types

export type RecordType =
    | { kind: 'record', fields: FieldMap }

export type VariantMap = Map<string, SimpleType>;
export type FieldMap = Map<string, FieldType>;

export namespace Type {
    export const union = (variants: VariantMap): Type => ({ kind: 'union', variants });
    export const unit = (): FieldType => ({ kind: 'unit' });
    export const ref = (typeName: string, ref: M.Ref | null): RefType => (
        { kind: 'ref', typeName, ref });
    export const array = (type: FieldType): FieldType => ({ kind: 'array', type });
    export const set = (type: FieldType): FieldType => ({ kind: 'set', type });
    export const dictionary = (key: FieldType, value: FieldType): FieldType => (
        { kind: 'dictionary', key, value });
    export const record = (fields: FieldMap): RecordType => ({ kind: 'record', fields });
}

export const ANY_TYPE: FieldType = Type.ref('_.Value', null);
