import { action } from "mobx" ; import { fail , isMutable , isStateTreeNode , getStateTreeNode , IValidationContext , IValidationResult , typecheckInternal , typeCheckFailure , typeCheckSuccess , IStateTreeNode , IJsonPatch , getType , ObjectNode , IChildNodesMap , ModelPrimitive , normalizeIdentifier , AnyObjectNode , AnyNode , BaseNode , ScalarNode , getStateTreeNodeSafe , assertArg } from "../../internal" ; internal hidden export enum TypeFlags { String = 1 , Number = 1 << 1 , Boolean = 1 << 2 , Date = 1 << 3 , Literal = 1 << 4 , Array = 1 << 5 , Map = 1 << 6 , Object = 1 << 7 , Frozen = 1 << 8 , Optional = 1 << 9 , Reference = 1 << 10 , Identifier = 1 << 11 , Late = 1 << 12 , Refinement = 1 << 13 , Union = 1 << 14 , Null = 1 << 15 , Undefined = 1 << 16 , Integer = 1 << 17 , Custom = 1 << 18 , SnapshotProcessor = 1 << 19 } internal hidden export const cannotDetermineSubtype = "cannotDetermine" ; hidden export type STNValue < T , IT extends IAnyType > = T extends object ? T & IStateTreeNode < IT > : T ; hidden const $type = Symbol ( "$type" ) ; /**
 * A type, either complex or simple.
 */ export interface IType < C , S , T > { hidden readonly [ $type ] : undefined ; /**
     * Friendly type name.
     */ name : string ; /**
     * Name of the identifier attribute or null if none.
     */ readonly identifierAttribute ? : string ; returns create ( snapshot ? , env ? ) : this [ "Type" ] ; param thing returns is ( thing ) : thing is C | this [ "Type" ] ; param thing param context returns validate ( thing , context ) : IValidationResult ; /**
     * Gets the textual representation of the type as a string.
     */ describe ( ) : string ; deprecated hidden readonly Type : STNValue < T , this > ; deprecated hidden readonly TypeWithoutSTN : T ; deprecated hidden readonly SnapshotType : S ; deprecated hidden readonly CreationType : C ; internal hidden flags : TypeFlags ; internal hidden isType : true ; internal hidden instantiate ( parent , subpath , environment , initialValue ) : BaseNode < C , S , T > ; internal hidden reconcile ( current , newValue , parent , subpath ) : BaseNode < C , S , T > ; internal hidden getSnapshot ( node , applyPostProcess ? ) : S ; internal hidden isAssignableFrom ( type ) : boolean ; internal hidden getSubTypes ( ) : IAnyType [ ] | IAnyType | null | typeof cannotDetermineSubtype ; } /**
 * Any kind of type.
 */ export interface IAnyType extends IType < any , any , any > { } /**
 * A simple type, this is, a type where the instance and the snapshot representation are the same.
 */ export interface ISimpleType < T > extends IType < T , T , T > { } hidden export type Primitives = ModelPrimitive | null | undefined ; deprecated hidden export interface IComplexType < C , S , T > extends IType < C , S , T & object > { } /**
 * Any kind of complex type.
 */ export interface IAnyComplexType extends IType < any , any , object > { } hidden export type ExtractCSTWithoutSTN < IT extends { [ $type ] : undefined ; CreationType : any ; SnapshotType : any ; TypeWithoutSTN : any ; } > = IT [ "CreationType" ] | IT [ "SnapshotType" ] | IT [ "TypeWithoutSTN" ] ; hidden export type ExtractCSTWithSTN < IT extends { [ $type ] : undefined ; CreationType : any ; SnapshotType : any ; Type : any ; } > = IT [ "CreationType" ] | IT [ "SnapshotType" ] | IT [ "Type" ] ; /**
 * The instance representation of a given type.
 */ export type Instance < T > = T extends { [ $type ] : undefined ; Type : any ; } ? T [ "Type" ] : T ; /**
 * The input (creation) snapshot representation of a given type.
 */ export type SnapshotIn < T > = T extends { [ $type ] : undefined ; CreationType : any ; } ? T [ "CreationType" ] : T extends IStateTreeNode < infer IT > ? IT [ "CreationType" ] : T ; /**
 * The output snapshot representation of a given type.
 */ export type SnapshotOut < T > = T extends { [ $type ] : undefined ; SnapshotType : any ; } ? T [ "SnapshotType" ] : T extends IStateTreeNode < infer IT > ? IT [ "SnapshotType" ] : T ; /**
 * A type which is equivalent to the union of SnapshotIn and Instance types of a given typeof TYPE or typeof VARIABLE.
 * For primitives it defaults to the primitive itself.
 *
 * For example:
 * - `SnapshotOrInstance<typeof ModelA> = SnapshotIn<typeof ModelA> | Instance<typeof ModelA>`
 * - `SnapshotOrInstance<typeof self.a (where self.a is a ModelA)> = SnapshotIn<typeof ModelA> | Instance<typeof ModelA>`
 *
 * Usually you might want to use this when your model has a setter action that sets a property.
 *
 * Example:
 * ```ts
 * const ModelA = types.model({
 *   n: types.number
 * })
 *
 * const ModelB = types.model({
 *   innerModel: ModelA
 * }).actions(self => ({
 *   // this will accept as property both the snapshot and the instance, whichever is preferred
 *   setInnerModel(m: SnapshotOrInstance<typeof self.innerModel>) {
 *     self.innerModel = cast(m)
 *   }
 * }))
 * ```
 */ export type SnapshotOrInstance < T > = SnapshotIn < T > | Instance < T > ; internal hidden export abstract class BaseType < C , S , T , N extends BaseNode < any , any , any > = BaseNode < C , S , T > > implements IType < C , S , T > { [ $type ] ! : undefined ; readonly C ! : C ; readonly S ! : S ; readonly T ! : T ; readonly N ! : N ; readonly isType = true ; readonly name : string ; constructor ( name ) { this . name = name ; } create ( snapshot ? , environment ? ) { typecheckInternal ( this , snapshot ) ; return this . instantiate ( null , "" , environment , snapshot ! ) . value ; } getSnapshot ( node , applyPostProcess ? ) { throw fail ( "unimplemented method" ) ; } abstract reconcile ( current , newValue , parent , subpath ) ; abstract instantiate ( parent , subpath , environment , initialValue ) ; declare abstract flags : TypeFlags ; abstract describe ( ) ; abstract isValidSnapshot ( value , context ) ; isAssignableFrom ( type ) { return type === this ; } validate ( value , context ) { const node = getStateTreeNodeSafe ( value ) ; if ( node ) { const valueType = getType ( value ) ; return this . isAssignableFrom ( valueType ) ? typeCheckSuccess ( ) : typeCheckFailure ( context , value ) ; } return this . isValidSnapshot ( value as C , context ) ; } is ( thing ) { return this . validate ( thing , [ { path : "" , type : this } ] ) . length === 0 ; } get Type ( ) : any { throw fail ( "Factory.Type should not be actually called. It is just a Type signature that can be used at compile time with Typescript, by using `typeof type.Type`" ) ; } get TypeWithoutSTN ( ) : any { throw fail ( "Factory.TypeWithoutSTN should not be actually called. It is just a Type signature that can be used at compile time with Typescript, by using `typeof type.TypeWithoutSTN`" ) ; } get SnapshotType ( ) : any { throw fail ( "Factory.SnapshotType should not be actually called. It is just a Type signature that can be used at compile time with Typescript, by using `typeof type.SnapshotType`" ) ; } get CreationType ( ) : any { throw fail ( "Factory.CreationType should not be actually called. It is just a Type signature that can be used at compile time with Typescript, by using `typeof type.CreationType`" ) ; } abstract getSubTypes ( ) ; } BaseType . prototype . create = action ( BaseType . prototype . create ) ; internal hidden export type AnyBaseType = BaseType < any , any , any , any > ; internal hidden export type ExtractNodeType < IT extends IAnyType > = IT extends BaseType < any , any , any , infer N > ? N : never ; internal hidden export abstract class ComplexType < C , S , T > extends BaseType < C , S , T , ObjectNode < C , S , T > > { identifierAttribute ? : string ; constructor ( name ) { super ( name ) ; } create ( snapshot = this . getDefaultSnapshot ( ) , environment ? ) { return super . create ( snapshot , environment ) ; } getValue ( node ) { node . createObservableInstanceIfNeeded ( ) ; return node . storedValue ; } abstract getDefaultSnapshot ( ) ; abstract createNewInstance ( childNodes ) ; abstract finalizeNewInstance ( node , instance ) ; abstract applySnapshot ( node , snapshot ) ; abstract applyPatchLocally ( node , subpath , patch ) ; abstract processInitialSnapshot ( childNodes , snapshot ) ; abstract getChildren ( node ) ; abstract getChildNode ( node , key ) ; abstract getChildType ( propertyName ? ) ; abstract initializeChildNodes ( node , snapshot ) ; abstract removeChild ( node , subpath ) ; isMatchingSnapshotId ( current , snapshot ) { return ( ! current . identifierAttribute || current . identifier === normalizeIdentifier ( ( snapshot as any ) [ current . identifierAttribute ] ) ) ; } private tryToReconcileNode ( current , newValue ) { if ( current . isDetaching ) return false ; if ( ( current . snapshot as any ) === newValue ) { return true ; } if ( isStateTreeNode ( newValue ) && getStateTreeNode ( newValue ) === current ) { return true ; } if ( current . type === this && isMutable ( newValue ) && ! isStateTreeNode ( newValue ) && this . isMatchingSnapshotId ( current , newValue as any ) ) { current . applySnapshot ( newValue as C ) ; return true ; } return false ; } reconcile ( current , newValue , parent , subpath ) { const nodeReconciled = this . tryToReconcileNode ( current , newValue ) ; if ( nodeReconciled ) { current . setParent ( parent , subpath ) ; return current ; } current . die ( ) ; if ( isStateTreeNode ( newValue ) && this . isAssignableFrom ( getType ( newValue ) ) ) { const newNode = getStateTreeNode ( newValue ) ; newNode . setParent ( parent , subpath ) ; return newNode ; } return this . instantiate ( parent , subpath , undefined , newValue ) ; } getSubTypes ( ) { return null ; } } ComplexType . prototype . create = action ( ComplexType . prototype . create ) ; internal hidden export abstract class SimpleType < C , S , T > extends BaseType < C , S , T , ScalarNode < C , S , T > > { abstract instantiate ( parent , subpath , environment , initialValue ) ; createNewInstance ( snapshot ) { return snapshot as any ; } getValue ( node ) { return node . storedValue ; } getSnapshot ( node ) { return node . storedValue ; } reconcile ( current , newValue , parent , subpath ) { if ( ! current . isDetaching && current . type === this && current . storedValue === newValue ) { return current ; } const res = this . instantiate ( parent , subpath , undefined , newValue ) ; current . die ( ) ; return res ; } getSubTypes ( ) { return null ; } } param value returns export function isType ( value ) { return typeof value === "object" && value && value . isType === true ; } internal hidden export function assertIsType ( type , argNumber ) { assertArg ( type , isType , "mobx-state-tree type" , argNumber ) ; }