/**
 * Captures the form context and stores it in
 * a well known location for other components,
 * especially Web Resources.
 *
 * Since form scripts and web resources live
 * in a hierarchy of iframes, ensure that
 * we embed that knowledge here, once.
 *
 * Note that MS documents are incomplete about
 * the context and its validness after a callback
 * function exits.
 *
 * Usage: arrange to have onLoad called
 * as a form's onload handler.
 */

/** Attachment point for the callback. Object has "Deferred" type. */
function Deferred() {
    return defer(Object.create(Deferred.prototype))
}

/** Add resolve, reject, promise to an object. */
function defer(deferred) {
    deferred.promise = new Promise(function (resolve, reject) {
        deferred.resolve = resolve
        deferred.reject = reject
    })
    return deferred
}

const p = Deferred()

/**
 * Arrange to have this function called
 * with the form's OnLoad event. This is
 * the only way to guarantee that we obtain
 * a valid form context without going through
 * the deprecated Xrm.Page.
 *
 * This form assumes that form scripts load
 * into a frame hierarchy that is one below
 * a parent that webresources can also access.
 */
export function onLoad(ctx: any): void {
    p.resolve(ctx.getFormContext())
}

/**
 * Attach our promise one level up so other frames can find it.  To reach the
 * promised land, use `FormContextP` to obtain the promise that you can chain
 * off of. Use Promise.race (or equivalent) to timeout waiting. See `getXrmP.ts`
 * for a promise that waits for Xrm.FormContext through this or Xrm.Page. You can
* also just check for it using the strict value `(window.parent as any).FormContextP`.
 */
// @ts-ignore
window.parent.FormContextP = p.promise
