/**
 * The objectFit sets how the content of an element should be resized to fit its container.
 *
 * `contain`:
 *
 *  The content is scaled to maintain its aspect ratio while fitting within the element's
 *  content box. The entire object is made to fill the box, while preserving its aspect ratio,
 *  so the object will be "letterboxed" or "pillarboxed" if its aspect ratio does not match the
 *  aspect ratio of the box.
 *
 * `cover`:
 *
 *  The content is sized to maintain its aspect ratio while filling the element's entire
 *  content box. If the object's aspect ratio does not match the aspect ratio of its box, then
 *  the object will be clipped to fit.
 *
 * `none`:
 *
 *  The content is not resized.
 * @enum
 */
declare const objectFit: {
    readonly CONTAIN: "contain";
    readonly COVER: "cover";
    readonly NONE: "none";
};
type ObjectFit = typeof objectFit[keyof typeof objectFit];

interface VideoElementSize {
    width: number;
    height: number;
    offsetX: number;
    offsetY: number;
}

interface Centroids {
    [id: string]: {x: number, y: number };
}

interface MeshAnnotation {
    x: number;
    y: number;
    z: number | undefined;
}

interface Annotations {
    silhouette: MeshAnnotation[],
    centroids: Centroids;
}

interface PosePoints {
    [x: string]: {
        point: number[],
        valid: boolean;
        estimated: boolean;
        quality: number;
    }  
}

interface DfxRect {
    x: number;
    y: number;
    width: number;
    height: number;
}

interface DfxFace {
    detected: boolean;
    id: string;
    poseValid: boolean;
    posePoints: PosePoints,
    faceRect: DfxRect;
}

declare const pointGroup: {
    readonly METADATA: "metadata";
    readonly PHYSICAL: "physical";
    readonly GENERAL_RISKS: "generalRisks";
    readonly VITALS: "vitals";
    readonly PHYSIOLOGICAL: "physiological";
    readonly METABOLIC_RISKS: "metabolicRisks";
    readonly BLOOD_BIOMARKERS: "bloodBiomarkers";
    readonly OVERALL: "overall";
    readonly MENTAL: "mental";
    readonly SURVEYS: "surveys";
};

interface MeasurementOptions {
    userProfileId?: string;
    partnerId?: string;
}
interface LoggerSettings {
    mediaPipe?: boolean;
    beforeRESTCall?: boolean;
    afterRESTCall?: boolean;
    extractionLibWasm?: boolean;
    apiClient?: boolean;
    webSocket?: boolean;
    extractionWorker?: boolean;
    faceTrackerWorkers?: boolean;
    sdk?: boolean;
}
interface Settings {
    mediaElement: HTMLDivElement;
    assetFolder: string;
    apiUrl?: string;
    logger?: LoggerSettings;
    metrics?: boolean;
    mirrorVideo?: boolean;
    displayMediaStream?: boolean;
}
interface Demographics {
    age: number;
    height: number;
    weight: number;
    sex: number;
    smoking: number;
    bloodPressureMedication: number;
    diabetes: number;
    unit: 'Metric' | 'Imperial';
}
interface ResultsError {
    code: string;
    errors: {
        [x: string]: {
            messages: string[];
        };
    };
}
type PointGroupType = typeof pointGroup[keyof typeof pointGroup];
interface IMeta {
    availableAfterSec: number;
    range: {
        min: number;
        max: number;
    };
    requirements: {
        profileInfo: boolean;
        medicalHistory: boolean;
    };
    group: PointGroupType;
    ranges: {
        [x: string]: number[][][];
    };
}
interface Point {
    channel: string;
    notes: string[];
    value: string;
    meta: IMeta;
    info: {
        name: string;
        description: string;
        unit: string;
    };
}
interface Points {
    [x: string]: Point;
}
interface Results {
    measurementId: string;
    measurementResultId: string;
    resultsOrder: number;
    finalChunkNumber: number;
    points: Points;
    errors: ResultsError;
    statusId: string;
}
type IsoDate = `${number}-${number}-${number}T${number}:${number}:${number}.${number}Z`;
interface SDKVersion {
    webSDK: string;
    extractionLib: {
        version: string;
        sdkId: string;
    };
    faceTracker: string;
}
interface Drawables {
    face: DfxFace;
    annotations: Annotations;
    starRating: number;
}
interface IMediaElementSize {
    width: number;
    height: number;
    x: number;
    y: number;
}
interface IFrameInfo {
    mediaStreamWidth: number;
    mediaStreamHeight: number;
    faceTrackerWidth: number;
    faceTrackerHeight: number;
}
interface IMaskResize {
    mediaElementSize: IMediaElementSize;
    videoElementSize: VideoElementSize;
    frameInfo: IFrameInfo;
}
interface MediaElementResizeEvent extends CustomEvent {
    detail: IMaskResize;
}

/**
 * Face attribute values used to define demographic information
 * @enum
 */
declare const faceAttributeValue: {
    readonly SEX_NOT_PROVIDED: 1;
    readonly SEX_ASSIGNED_MALE_AT_BIRTH: 2;
    readonly SEX_ASSIGNED_FEMALE_AT_BIRTH: 3;
    readonly DIABETES_NONE: 4;
    readonly DIABETES_TYPE1: 5;
    readonly DIABETES_TYPE2: 6;
    readonly SMOKER_TRUE: 0;
    readonly SMOKER_FALSE: 1;
    readonly BLOOD_PRESSURE_MEDICATION_TRUE: 1;
    readonly BLOOD_PRESSURE_MEDICATION_FALSE: 0;
};
/**
 * Face tracker states
 * @enum
 */
declare const faceTrackerState: {
    readonly ASSETS_NOT_DOWNLOADED: "ASSETS_NOT_DOWNLOADED";
    readonly NOT_LOADED: "NOT_LOADED";
    readonly LOADING: "LOADING";
    readonly LOADED: "LOADED";
    readonly READY: "READY";
};
type FaceTrackerStateType = typeof faceTrackerState[keyof typeof faceTrackerState];

type ChunkAction = 'CHUNK::PROCESS' | 'FIRST::PROCESS' | 'LAST::PROCESS';

/**
 * Constraint Feedback
 * 
 * FaceNone: No face detected, move face into target region.
 * 
 * FaceOffTarget: Face not in target region, move face into target region.
 * 
 * FaceDirection: Not looking at camera, look straight at the camera.
 * 
 * FaceFar: Too far from camera, move closer to the camera.
 * 
 * FaceMovement: Moving too much, hold still.
 * 
 * ImageBright: Image too bright, try a darker room.
 * 
 * ImageDark: Image too dark, try a brighter room.
 * 
 * ImageQuality: Bad image quality, improve image quality - try alternate webcam.
 * 
 * ImageBackLit: Backlit face, remove backlight behind face.
 * 
 * LowFps: Framerate too low, try alternate webcam or a brighter room.
 * 
 */
type ConstraintFeedback = 
    "FaceNone" |
    "FaceOffTarget" |
    "FaceDirection" |
    "FaceFar" |
    "FaceMovement" |
    "ImageBright" |
    "ImageDark" |
    "ImageQuality" |
    "ImageBackLit" |
    "LowFps";

/**
 * Constraint Feedback
 * 
 * Good: indicates there is nothing presently detected in constraints
 * 
 * Warn: indicates a problem that needs to be corrected
 * 
 * Error: indicates a problem that has failed the measurement
 */
type ConstraintStatus = "Good" | "Warn" | "Error";

interface ChunkSent {
    data: {
        Params: {
            ID: string;
        };
        Action: ChunkAction;
        Payload: string;
    };
    chunkNumber: number;
    numberChunks: number;
    startTime_s: number;
    endTime_s: number;
    duration_s: number;
    metadata: Uint8Array;
}

declare class Measurement {
    #private;
    readonly on: {
        /**
         * before REST call
         * @param {IsoDate} timestamp - timestamp of the event
         */
        beforeRESTCall: ((timestamp: IsoDate, actionId: number) => void) | null;
        /**
         * after REST call
         * @param {IsoDate} timestamp - timestamp of the event
         * @param {string} status - HTTP status code
         * @param {unknown} error - error object
         */
        afterRESTCall: ((timestamp: IsoDate, actionId: number, status: string, error: unknown) => void) | null;
        /**
         * bytes downloaded
         * @param {number} bytes - number of bytes downloaded
         * @param {string} url - download URL
         * @param {boolean} done - true if download is complete
         */
        bytesDownloaded: ((bytes: number, url: string, done: boolean) => void) | null;
        /**
         * download error
         * @param {string} url - download URL
         * @param {unknown} error - error status
         */
        downloadError: ((url: string, error: unknown) => void) | null;
        /**
         * when face tracker state Changes
         * @param {faceTrackerState} state - face tracker state
         */
        faceTrackerStateChanged: ((state: FaceTrackerStateType) => void) | null;
        /**
         * when measurement results are received
         * @param {any} results - measurement results
         */
        resultsReceived: ((results: Results) => void) | null;
        /**
         * when measurement results are received
         * @param {any} results - measurement results
         */
        constraintsUpdated: ((feedback: ConstraintFeedback, status: ConstraintStatus) => void) | null;
        /**
         * When media element size changes
         * @param {event} MediaElementResizeEvent
         */
        mediaElementResize: ((event: MediaElementResizeEvent) => void) | null;
        /**
         * When facial landmarks are updated
         * @param {drawables} Drawables
         */
        facialLandmarksUpdated: ((drawables: Drawables) => void) | null;
        /**
         * When a chunk is sent to DeepAffex
         * @param {chunkSent} ChunkSent
         */
        chunkSent: ((chunkSent: ChunkSent) => void) | null;
    };
    /**
     * Initialize the Measurement SDK
     * @param {object} settings - Initialization settings
     * @returns Promise<Measurement>
     */
    static init(settings: Settings): Promise<Measurement>;
    private constructor();
    loadMask(element: SVGSVGElement): void;
    /**
     * Set settings
     * @param {Settings} newSettings
     * @returns {boolean} true if success
     */
    setSettings(newSettings: Partial<Settings>): boolean;
    /**
     * Returns version number
     * @returns {SDKVersion} version - [Web SDK, DFX Extraction Lib, Face Tracker]
     */
    getVersion(): SDKVersion;
    /**
     * Check if SIMD is supported and then download the supported MediaPipe
     * face traker assets for the runtime environment
     * It also downloads the extraction lib assets
     * @returns true if successfully download all files
     */
    downloadAssets(): Promise<boolean | undefined>;
    /**
     * Set extraction library settings
     * @param {number} numberofChunks Number of chunks for extraction library collector
     * @param {number} targetFPS Target FPS for extraction library collector
     * @param {number} chunkDurationSeconds Chunk duration in seconds for extraction library collector
     */
    setExtractionLibSettings(numberofChunks?: number, targetFPS?: number, chunkDurationSeconds?: number): void;
    /**
     * Set the action for the next chunk to LAST::PROCESS
    */
    setNextChunkAsFinal(): Promise<void>;
    startTracking(): Promise<void>;
    stopTracking(): Promise<void>;
    destroy(): Promise<void>;
    setMediaStream(mediaStream: MediaStream): Promise<void>;
    prepare(token: string, refreshToken: string, studyId: string, sdkId?: string): Promise<void>;
    startMeasurement(measurementOptions?: MeasurementOptions): Promise<void>;
    setDemographics(demographics: Demographics): void;
    setObjectFit(fit: ObjectFit): boolean;
}

export { type ChunkSent, type ConstraintFeedback, type ConstraintStatus, type Demographics, type Drawables, type FaceTrackerStateType, type IsoDate, Measurement, type MeasurementOptions, type MediaElementResizeEvent, type Results, type Settings, faceAttributeValue, faceTrackerState };
