import { AclEvaluationInterface, AclTag } from '@allianz/taly-acl';
import { EventEmitter } from '@angular/core';
import { UntypedFormGroup } from '@angular/forms';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { ValidationConfigItem } from '../form-support/validation.model';
import { ValidationRule } from '../validation-config.model';
import { BUILDING_BLOCK_NAVIGATION_TYPE, BuildingBlockNavigationEvent } from './navigation';
/**
* The bare minimum for a Building Block
*/
interface BuildingBlockBase {
id: string;
completion$: BehaviorSubject<boolean>;
disconnected$: Subject<void>;
connected$: Subject<void>;
acl: AclEvaluationInterface;
aclTag: AclTag | null;
readonly loadingStatus$: Observable<Record<string, boolean>>;
navigateEvent$: EventEmitter<BuildingBlockNavigationEvent>;
navigate(type: BUILDING_BLOCK_NAVIGATION_TYPE, payload?: string): void;
// lifecycle
onPageConnection(): void;
onPageDisconnected(): void;
setValidationConfiguration(data: ValidationConfigItem[]): void;
/**
* This EventEmitter can be used to update a validation configuration during runtime.
* The primary use case for this is the Dynamic Form.
*/
validationConfigurationChanged$: EventEmitter<ValidationRule[]>;
trackForm$: EventEmitter<UntypedFormGroup>;
}
/**
* How to provide data we need to work properly
* This cna be lists for Dropdowns, data to display only, image urls etc
*/
interface Resourceable<U> {
resources: U;
// 01. provide data to work
setResources(data: U): void;
}
/**
* Manage Building Block State
*/
interface Stateable<T> {
state: T;
stateChange$: Subject<T>;
// to be called whenever the state has changed
// so the facade knows about it and can store the current data
stateChanged(): void;
// 03. Restore or read the actual contracted data for this Building Block
setState(state: T): void;
getState(): T;
}
interface Editable {
getForm(): UntypedFormGroup | undefined;
}
export interface Deferred<T = unknown> {
promise: Promise<T>;
resolve: (response?: undefined) => void;
reject: (error?: Error) => void;
}
export interface BusinessEvent {
event: string;
deferred: Deferred;
}
interface BusinessEventAble {
businesssEventCall$: EventEmitter<BusinessEvent>;
}
/**
* That's the core contract a Building Block needs to fulfill.
* Any actual implementation needs to inherit from the Abstract component
* in order to be technically discoverable by a Building Block collecting page.
*/
export interface BuildingBlockInterface<
T = Record<string, unknown>,
U = Record<string, unknown> | undefined
> extends BuildingBlockBase,
Stateable<T>,
Resourceable<U>,
BusinessEventAble,
Editable {}