() => {
    const parent: SpanContext = {
      traceId: '00112233445566778899001122334455',
      spanId: '0011223344556677',
      traceFlags: TraceFlags.SAMPLED,
    };
    const context = trace.setSpanContext(ROOT_CONTEXT, parent);

    const sp: SpanProcessor = new DummySpanProcessor();
    const onStartSpy = sinon.spy(sp, 'onStart');
    const tp = new BasicTracerProvider();
    tp.addSpanProcessor(sp);

    const sampler: Sampler = new AlwaysOnSampler();
    const shouldSampleSpy = sinon.spy(sampler, 'shouldSample');
    const tracer = new Tracer({ name: 'default' }, { sampler }, tp);
    const span = tracer.startSpan('a', {}, context) as Span;
    assert.strictEqual(span.parentSpanId, parent.spanId);
    sinon.assert.calledOnceWithExactly(shouldSampleSpy, context, parent.traceId, 'a', SpanKind.INTERNAL, {}, []);
    sinon.assert.calledOnceWithExactly(onStartSpy, span, context);
  }


() => {
    const parent: SpanContext = {
      traceId: '00112233445566778899001122334455',
      spanId: '0011223344556677',
      traceFlags: TraceFlags.SAMPLED,
    };
    const context = trace.setSpanContext(ROOT_CONTEXT, parent);

    const sp: SpanProcessor = new DummySpanProcessor();
    const onStartSpy = sinon.spy(sp, 'onStart');
    const tp = new BasicTracerProvider();
    tp.addSpanProcessor(sp);

    const sampler: Sampler = new AlwaysOnSampler();
    const shouldSampleSpy = sinon.spy(sampler, 'shouldSample');
    const tracer = new Tracer({ name: 'default' }, { sampler }, tp);
    const span = tracer.startSpan('a', { root: true }, context) as Span;
    assert.strictEqual(span.parentSpanId, undefined);
    sinon.assert.calledOnce(shouldSampleSpy);
    sinon.assert.calledOnce(onStartSpy);
    const samplerContext = shouldSampleSpy.firstCall.args[0];
    const processorContext = onStartSpy.firstCall.args[1];
    assert.strictEqual(samplerContext, processorContext);
    assert.strictEqual(getSpan(samplerContext), undefined);
  }


() => {
    envSource.OTEL_TRACES_SAMPLER = 'traceidratio';
    envSource.OTEL_TRACES_SAMPLER_ARG = '';
    const tracer = new Tracer(
      { name: 'default', version: '0.0.1' },
      {},
      tracerProvider
    );
    const span = tracer.startSpan('my-span');
    const context = span.spanContext();
    assert.strictEqual(context.traceFlags, TraceFlags.SAMPLED);
    span.end();
  }


() => {
    envSource.OTEL_TRACES_SAMPLER = 'traceidratio';
    envSource.OTEL_TRACES_SAMPLER_ARG = '2';
    const tracer = new Tracer(
      { name: 'default', version: '0.0.1' },
      {},
      tracerProvider
    );
    const span = tracer.startSpan('my-span');
    const context = span.spanContext();
    assert.strictEqual(context.traceFlags, TraceFlags.SAMPLED);
    span.end();
  }


() => {
    envSource.OTEL_TRACES_SAMPLER = 'traceidratio';
    envSource.OTEL_TRACES_SAMPLER_ARG = '0';
    const tracer = new Tracer(
      { name: 'default', version: '0.0.1' },
      {},
      tracerProvider
    );
    const span = tracer.startSpan('my-span');
    const context = span.spanContext();
    assert.strictEqual(context.traceFlags, TraceFlags.NONE);
    span.end();
  }


() => {
    const tracer = new Tracer(
      { name: 'default', version: '0.0.1' },
      { sampler: new TestSampler() },
      tracerProvider
    );

    const spy = sinon.spy(tracer, 'startSpan');

    assert.strictEqual(tracer.startActiveSpan('my-span', span => {
      try {
        assert(spy.calledWith('my-span'));
        assert.strictEqual(getSpan(context.active()), span);
        return 1;
      } finally {
        span.end();
      }
    }), 1);
  }


span => {
      try {
        assert(spy.calledWith('my-span'));
        assert.strictEqual(getSpan(context.active()), span);
        return 1;
      } finally {
        span.end();
      }
    }


() => {
    const tracer = new Tracer(
      { name: 'default', version: '0.0.1' },
      { sampler: new TestSampler() },
      tracerProvider
    );

    const spy = sinon.spy(tracer, 'startSpan');

    assert.strictEqual(tracer.startActiveSpan('my-span', {attributes: {foo: 'bar'}}, span => {
      try {
        assert(spy.calledWith('my-span', {attributes: {foo: 'bar'}}));
        assert.strictEqual(getSpan(context.active()), span);
        return 1;
      } finally {
        span.end();
      }
    }), 1);
  }


span => {
      try {
        assert(spy.calledWith('my-span', {attributes: {foo: 'bar'}}));
        assert.strictEqual(getSpan(context.active()), span);
        return 1;
      } finally {
        span.end();
      }
    }


() => {
    const tracer = new Tracer(
      { name: 'default', version: '0.0.1' },
      { sampler: new TestSampler() },
      tracerProvider
    );

    const ctxKey = createContextKey('foo');

    const ctx = context.active().setValue(ctxKey, 'bar');

    const spy = sinon.spy(tracer, 'startSpan');

    assert.strictEqual(tracer.startActiveSpan('my-span', {attributes: {foo: 'bar'}}, ctx, span => {
      try {
        assert(spy.calledWith('my-span', {attributes: {foo: 'bar'}}, ctx));
        assert.strictEqual(getSpan(context.active()), span);
        assert.strictEqual(ctx.getValue(ctxKey), 'bar');
        return 1;
      } finally {
        span.end();
      }
    }), 1);
  }


span => {
      try {
        assert(spy.calledWith('my-span', {attributes: {foo: 'bar'}}, ctx));
        assert.strictEqual(getSpan(context.active()), span);
        assert.strictEqual(ctx.getValue(ctxKey), 'bar');
        return 1;
      } finally {
        span.end();
      }
    }


() => {
    const tracer = new Tracer(
      { name: 'default', version: '0.0.1' },
      { sampler: new TestSampler() },
      tracerProvider
    );

    const attributes = { ...validAttributes, ...invalidAttributes } as unknown as SpanAttributes;
    const links = [{
      context: {
        traceId: 'b3cda95b652f4a1592b449d5929fda1b',
        spanId: '6e0c63257de34c92',
        traceFlags: TraceFlags.SAMPLED
      },
      attributes: { ...attributes },
    }];
    // TestSampler should validate the attributes and links.
    const span = tracer.startSpan('my-span', { attributes, links }) as Span;
    span.end();

    assert.deepStrictEqual(span.attributes, { ...validAttributes, testAttribute: 'foobar' });
    assert.strictEqual(span.links.length, 1);
    assert.deepStrictEqual(span.links[0].attributes, validAttributes);
  }


class TestSampler implements Sampler {
    shouldSample(_context: Context, _traceId: string, _spanName: string, _spanKind: SpanKind, attributes: SpanAttributes, links: Link[]) {
      // The attributes object should be valid.
      assert.deepStrictEqual(sanitizeAttributes(attributes), attributes);
      links.forEach(link => {
        assert.deepStrictEqual(sanitizeAttributes(link.attributes), link.attributes);
      });
      return {
        decision: SamplingDecision.RECORD_AND_SAMPLED,
        attributes: {
          testAttribute: 'foobar',
          // invalid attributes should be sanitized.
          ...invalidAttributes,
        } as unknown as SpanAttributes,
      };
    }
  }


class DummySpanProcessor implements SpanProcessor {
      forceFlush () {
        return Promise.resolve();
      }
      onStart() {}
      onEnd() {}
      shutdown() {
        return Promise.resolve();
      }
  }


shouldSample(_context: Context, _traceId: string, _spanName: string, _spanKind: SpanKind, attributes: SpanAttributes, links: Link[]) {
      // The attributes object should be valid.
      assert.deepStrictEqual(sanitizeAttributes(attributes), attributes);
      links.forEach(link => {
        assert.deepStrictEqual(sanitizeAttributes(link.attributes), link.attributes);
      });
      return {
        decision: SamplingDecision.RECORD_AND_SAMPLED,
        attributes: {
          testAttribute: 'foobar',
          // invalid attributes should be sanitized.
          ...invalidAttributes,
        } as unknown as SpanAttributes,
      };
    }


forceFlush () {
        return Promise.resolve();
      }


onStart() {}


onEnd() {}


shutdown() {
        return Promise.resolve();
      }


export type ThemeRecord = {
  colors?: Colors;
  fonts?: Fonts;
};


type Colors = {
  icon?: string;
  text?: string;
  background?: string;
  primary?: string;
  secondary?: string;
  highlight?: string;
};


type Fonts = {
  body?: string;
};


(query: string): string | undefined => {
    return document.querySelector(query)?.textContent;
  }


async () => {
    return presence.getStrings(
      {
        play: "general.playing",
        pause: "general.paused",
        live: "general.live",
        browse: "general.browsing",
        viewPage: "general.viewPage",
        home: "twitch.home",
        download: "twitch.downloads",
        jobs: "twitch.jobs",
        turbo: "twitch.turbo",
        partners: "twitch.partners",
        press: "twitch.press",
        security: "twitch.security",
        access: "twitch.access",
        ads: "twitch.ads",
        guidelines: "twitch.guidelines",
        terms: "general.terms",
        privacy: "general.privacy",
        cookie: "general.cookie",
        watchingLive: "general.watchingLive",
        watchingVid: "general.watchingVid",
        viewProfile: "general.viewProfile",
        viewCategory: "general.viewCategory",
        viewWallet: "twitch.wallet",
        viewEsports: "twitch.esports",
        viewFollow: "twitch.viewFollow",
        viewTeam: "twitch.viewTeam",
        viewDropsInv: "twitch.viewDropsInv",
        viewDropsComp: "twitch.viewDropsComp",
        viewing: "general.viewing",
        searchingFor: "general.searchFor",
        searchingSomething: "general.searchSomething",
        viewSettings: "twitch.viewSettings",
        viewFriends: "twitch.viewFriends",
        subs: "twitch.subs",
        squad: "twitch.squad",
        modStreamer: "twitch.modStreamer",
        readingAbout: "general.readingAbout",
        redeem: "twitch.redeem",
        camp: "twitch.camp",
        campBasic: "twitch.campBasic",
        campSetup: "twitch.campSetup",
        campLevel: "twitch.campLevel",
        campConnect: "twitch.campConnect",
        campReward: "twitch.campReward",
        campMusic: "twitch.campMusic",
        campLive: "twitch.campLive",
        dashboard: "twitch.dashboard",
        dashboardManage: "twitch.dashboardManage",
        manageRoles: "twitch.manageRoles",
        produce: "twitch.produce",
        viewTheir: "twitch.viewTheir",
        channelAnaly: "twitch.channelAnaly",
        streamSum: "twitch.streamSum",
        achievements: "twitch.achievements",
        activity: "twitch.activity",
        followList: "twitch.followList",
        colls: "twitch.colls",
        clips: "twitch.clips",
        channelSettings: "twitch.channelSettings",
        moderationSettings: "twitch.moderationSettings",
        dropsSettings: "twitch.dropsSettings",
        tools: "twitch.tools",
        extensions: "twitch.extensions",
        brand: "twitch.brand",
        brandReal: "twitch.brandReal",
        brandMadness: "twitch.brandMadness",
        brandExpression: "twitch.brandExpression",
        brandTogether: "twitch.brandTogether",
        brandWatch: "twitch.brandWatch",
        blogArchive: "twitch.blogArchive",
        readingArticle: "general.readingArticle",
        blogBrowse: "twitch.blogBrowse",
        blogs: "twitch.blogs",
        help: "twitch.help",
        helpTopic: "twitch.helpTopic",
        helpTopicCatalog: "twitch.helpTopicCatalog",
        affiliate: "twitch.affiliate",
        dev: "twitch.dev",
        devProduct: "twitch.devProduct",
        devShowcase: "twitch.devShowcase",
        devSupport: "twitch.devSupport",
        devDocs: "twitch.devDocs",
        incident: "general.incidentHistory",
        uptime: "general.uptimeHistory",
        forums: "general.forums",
        thread: "general.readingThread",
        user: "general.viewUser",
        watchStream: "general.buttonWatchStream",
        watchVideo: "general.buttonWatchVideo"
      },
      oldLang
    );
  }


() => "en"


word => word.charAt(0).toUpperCase() + word.slice(1)


squadUser => {
        squadNames.push(squadUser.textContent);
      }


function asyncDispatchMiddleware(api: MiddlewareAPI<DispatchTyped>): ReturnType<Middleware> {
  return (next: DispatchTyped) => (action: DispatchAction) => {
    let syncActivityFinished = false;
    let actionQueue: Array<AsyncActions> = [];

    const flushQueue = () => {
      actionQueue.forEach(a => api.dispatch(a as DispatchAction)); // flush queue
      actionQueue = [];
    };

    const asyncDispatch = (asyncAction: AsyncActions) => {
      actionQueue = actionQueue.concat([asyncAction]);

      if (syncActivityFinished) {
        flushQueue();
      }
    };

    const actionWithAsyncDispatch: DispatchAction = {
      ...action,
      asyncDispatch
    };

    next(actionWithAsyncDispatch);
    syncActivityFinished = true;
    flushQueue();
  };
}


(next: DispatchTyped) => (action: DispatchAction) => {
    let syncActivityFinished = false;
    let actionQueue: Array<AsyncActions> = [];

    const flushQueue = () => {
      actionQueue.forEach(a => api.dispatch(a as DispatchAction)); // flush queue
      actionQueue = [];
    };

    const asyncDispatch = (asyncAction: AsyncActions) => {
      actionQueue = actionQueue.concat([asyncAction]);

      if (syncActivityFinished) {
        flushQueue();
      }
    };

    const actionWithAsyncDispatch: DispatchAction = {
      ...action,
      asyncDispatch
    };

    next(actionWithAsyncDispatch);
    syncActivityFinished = true;
    flushQueue();
  }


(action: DispatchAction) => {
    let syncActivityFinished = false;
    let actionQueue: Array<AsyncActions> = [];

    const flushQueue = () => {
      actionQueue.forEach(a => api.dispatch(a as DispatchAction)); // flush queue
      actionQueue = [];
    };

    const asyncDispatch = (asyncAction: AsyncActions) => {
      actionQueue = actionQueue.concat([asyncAction]);

      if (syncActivityFinished) {
        flushQueue();
      }
    };

    const actionWithAsyncDispatch: DispatchAction = {
      ...action,
      asyncDispatch
    };

    next(actionWithAsyncDispatch);
    syncActivityFinished = true;
    flushQueue();
  }


() => {
      actionQueue.forEach(a => api.dispatch(a as DispatchAction)); // flush queue
      actionQueue = [];
    }


a => api.dispatch(a as DispatchAction)


(asyncAction: AsyncActions) => {
      actionQueue = actionQueue.concat([asyncAction]);

      if (syncActivityFinished) {
        flushQueue();
      }
    }


type DispatchTyped = Dispatch<DispatchAction>;


type AsyncActions = Interface.BasicAction | RSAAAction;


({ children, router }: Props) => {
    const [state, setState] = useState<{ state: State<Node<any>> | null }>({ state: router.state });
    useLayoutEffect(() => {
        const removeListner = router.addEventListener(events.TRANSITION_SUCCESS, ({ toState }: EventParamsNavigation<Node<any>>) => {
            setState({ state: toState });
        });

        return removeListner;
    }, [router]);

    return (
        <RouterContext.Provider value={router}>
            <RouterStateContext.Provider value={{ router: router, state: state.state }}>{children}</RouterStateContext.Provider>
        </RouterContext.Provider>


() => {
        const removeListner = router.addEventListener(events.TRANSITION_SUCCESS, ({ toState }: EventParamsNavigation<Node<any>>) => {
            setState({ state: toState });
        });

        return removeListner;
    }


({ toState }: EventParamsNavigation<Node<any>>) => {
            setState({ state: toState });
        }


type Props = { children: ReactNode; router: Router42<any> };


alerts => {
    console.log(JSON.stringify(alerts));
}


e => {
    console.log(e);
}


input => {
				const inputRowElement = messageContainer.appendChild($('.dialog-message-input'));

				const inputBox = this._register(new InputBox(inputRowElement, undefined, {
					placeholder: input.placeholder,
					type: input.type ?? 'text',
				}));

				if (input.value) {
					inputBox.value = input.value;
				}

				return inputBox;
			}


() => checkbox.checked = !checkbox.checked


(resolve) => {
			clearNode(this.buttonsContainer);

			const buttonBar = this.buttonBar = this._register(new ButtonBar(this.buttonsContainer));
			const buttonMap = this.rearrangeButtons(this.buttons, this.options.cancelId);

			// Handle button clicks
			buttonMap.forEach((entry, index) => {
				const button = this._register(buttonBar.addButton({ title: true }));
				button.label = mnemonicButtonLabel(buttonMap[index].label, true);

				this._register(button.onDidClick(e => {
					if (e) {
						EventHelper.stop(e);
					}

					resolve({
						button: buttonMap[index].index,
						checkboxChecked: this.checkbox ? this.checkbox.checked : undefined,
						values: this.inputs.length > 0 ? this.inputs.map(input => input.value) : undefined
					});
				}));
			});

			// Handle keyboard events gloably: Tab, Arrow-Left/Right
			this._register(domEvent(window, 'keydown', true)((e: KeyboardEvent) => {
				const evt = new StandardKeyboardEvent(e);

				if (evt.equals(KeyCode.Enter)) {

					// Enter in input field should OK the dialog
					if (this.inputs.some(input => input.hasFocus())) {
						EventHelper.stop(e);

						resolve({
							button: buttonMap.find(button => button.index !== this.options.cancelId)?.index ?? 0,
							checkboxChecked: this.checkbox ? this.checkbox.checked : undefined,
							values: this.inputs.length > 0 ? this.inputs.map(input => input.value) : undefined
						});
					}

					return; // leave default handling
				}

				if (evt.equals(KeyCode.Space)) {
					return; // leave default handling
				}

				let eventHandled = false;

				// Focus: Next / Previous
				if (evt.equals(KeyCode.Tab) || evt.equals(KeyCode.RightArrow) || evt.equals(KeyMod.Shift | KeyCode.Tab) || evt.equals(KeyCode.LeftArrow)) {

					// Build a list of focusable elements in their visual order
					const focusableElements: { focus: () => void }[] = [];
					let focusedIndex = -1;
					for (const input of this.inputs) {
						focusableElements.push(input);
						if (input.hasFocus()) {
							focusedIndex = focusableElements.length - 1;
						}
					}

					if (this.checkbox) {
						focusableElements.push(this.checkbox);
						if (this.checkbox.hasFocus()) {
							focusedIndex = focusableElements.length - 1;
						}
					}

					if (this.buttonBar) {
						for (const button of this.buttonBar.buttons) {
							focusableElements.push(button);
							if (button.hasFocus()) {
								focusedIndex = focusableElements.length - 1;
							}
						}
					}

					// Focus next element (with wrapping)
					if (evt.equals(KeyCode.Tab) || evt.equals(KeyCode.RightArrow)) {
						if (focusedIndex === -1) {
							focusedIndex = 0; // default to focus first element if none have focus
						}

						const newFocusedIndex = (focusedIndex + 1) % focusableElements.length;
						focusableElements[newFocusedIndex].focus();
					}

					// Focus previous element (with wrapping)
					else {
						if (focusedIndex === -1) {
							focusedIndex = focusableElements.length; // default to focus last element if none have focus
						}

						let newFocusedIndex = focusedIndex - 1;
						if (newFocusedIndex === -1) {
							newFocusedIndex = focusableElements.length - 1;
						}

						focusableElements[newFocusedIndex].focus();
					}

					eventHandled = true;
				}

				if (eventHandled) {
					EventHelper.stop(e, true);
				} else if (this.options.keyEventProcessor) {
					this.options.keyEventProcessor(evt);
				}
			}));

			this._register(domEvent(window, 'keyup', true)((e: KeyboardEvent) => {
				EventHelper.stop(e, true);
				const evt = new StandardKeyboardEvent(e);

				if (evt.equals(KeyCode.Escape)) {
					resolve({
						button: this.options.cancelId || 0,
						checkboxChecked: this.checkbox ? this.checkbox.checked : undefined
					});
				}
			}));

			// Detect focus out
			this._register(domEvent(this.element, 'focusout', false)((e: FocusEvent) => {
				if (!!e.relatedTarget && !!this.element) {
					if (!isAncestor(e.relatedTarget as HTMLElement, this.element)) {
						this.focusToReturn = e.relatedTarget as HTMLElement;

						if (e.target) {
							(e.target as HTMLElement).focus();
							EventHelper.stop(e, true);
						}
					}
				}
			}));

			const spinModifierClassName = 'codicon-modifier-spin';

			this.iconElement.classList.remove(...dialogErrorIcon.classNamesArray, ...dialogWarningIcon.classNamesArray, ...dialogInfoIcon.classNamesArray, ...Codicon.loading.classNamesArray, spinModifierClassName);

			if (this.options.icon) {
				this.iconElement.classList.add(...this.options.icon.classNamesArray);
			} else {
				switch (this.options.type) {
					case 'error':
						this.iconElement.classList.add(...dialogErrorIcon.classNamesArray);
						break;
					case 'warning':
						this.iconElement.classList.add(...dialogWarningIcon.classNamesArray);
						break;
					case 'pending':
						this.iconElement.classList.add(...Codicon.loading.classNamesArray, spinModifierClassName);
						break;
					case 'none':
					case 'info':
					case 'question':
					default:
						this.iconElement.classList.add(...dialogInfoIcon.classNamesArray);
						break;
				}
			}

			const actionBar = this._register(new ActionBar(this.toolbarContainer, {}));

			const action = this._register(new Action('dialog.close', nls.localize('dialogClose', "Close Dialog"), dialogCloseIcon.classNames, true, async () => {
				resolve({
					button: this.options.cancelId || 0,
					checkboxChecked: this.checkbox ? this.checkbox.checked : undefined
				});
			}));

			actionBar.push(action, { icon: true, label: false, });

			this.applyStyles();

			this.element.setAttribute('aria-label', this.getAriaLabel());
			show(this.element);

			// Focus first element (input or button)
			if (this.inputs.length > 0) {
				this.inputs[0].focus();
				this.inputs[0].select();
			} else {
				buttonMap.forEach((value, index) => {
					if (value.index === 0) {
						buttonBar.buttons[index].focus();
					}
				});
			}
		}


(entry, index) => {
				const button = this._register(buttonBar.addButton({ title: true }));
				button.label = mnemonicButtonLabel(buttonMap[index].label, true);

				this._register(button.onDidClick(e => {
					if (e) {
						EventHelper.stop(e);
					}

					resolve({
						button: buttonMap[index].index,
						checkboxChecked: this.checkbox ? this.checkbox.checked : undefined,
						values: this.inputs.length > 0 ? this.inputs.map(input => input.value) : undefined
					});
				}));
			}


e => {
					if (e) {
						EventHelper.stop(e);
					}

					resolve({
						button: buttonMap[index].index,
						checkboxChecked: this.checkbox ? this.checkbox.checked : undefined,
						values: this.inputs.length > 0 ? this.inputs.map(input => input.value) : undefined
					});
				}


input => input.value


(e: KeyboardEvent) => {
				const evt = new StandardKeyboardEvent(e);

				if (evt.equals(KeyCode.Enter)) {

					// Enter in input field should OK the dialog
					if (this.inputs.some(input => input.hasFocus())) {
						EventHelper.stop(e);

						resolve({
							button: buttonMap.find(button => button.index !== this.options.cancelId)?.index ?? 0,
							checkboxChecked: this.checkbox ? this.checkbox.checked : undefined,
							values: this.inputs.length > 0 ? this.inputs.map(input => input.value) : undefined
						});
					}

					return; // leave default handling
				}

				if (evt.equals(KeyCode.Space)) {
					return; // leave default handling
				}

				let eventHandled = false;

				// Focus: Next / Previous
				if (evt.equals(KeyCode.Tab) || evt.equals(KeyCode.RightArrow) || evt.equals(KeyMod.Shift | KeyCode.Tab) || evt.equals(KeyCode.LeftArrow)) {

					// Build a list of focusable elements in their visual order
					const focusableElements: { focus: () => void }[] = [];
					let focusedIndex = -1;
					for (const input of this.inputs) {
						focusableElements.push(input);
						if (input.hasFocus()) {
							focusedIndex = focusableElements.length - 1;
						}
					}

					if (this.checkbox) {
						focusableElements.push(this.checkbox);
						if (this.checkbox.hasFocus()) {
							focusedIndex = focusableElements.length - 1;
						}
					}

					if (this.buttonBar) {
						for (const button of this.buttonBar.buttons) {
							focusableElements.push(button);
							if (button.hasFocus()) {
								focusedIndex = focusableElements.length - 1;
							}
						}
					}

					// Focus next element (with wrapping)
					if (evt.equals(KeyCode.Tab) || evt.equals(KeyCode.RightArrow)) {
						if (focusedIndex === -1) {
							focusedIndex = 0; // default to focus first element if none have focus
						}

						const newFocusedIndex = (focusedIndex + 1) % focusableElements.length;
						focusableElements[newFocusedIndex].focus();
					}

					// Focus previous element (with wrapping)
					else {
						if (focusedIndex === -1) {
							focusedIndex = focusableElements.length; // default to focus last element if none have focus
						}

						let newFocusedIndex = focusedIndex - 1;
						if (newFocusedIndex === -1) {
							newFocusedIndex = focusableElements.length - 1;
						}

						focusableElements[newFocusedIndex].focus();
					}

					eventHandled = true;
				}

				if (eventHandled) {
					EventHelper.stop(e, true);
				} else if (this.options.keyEventProcessor) {
					this.options.keyEventProcessor(evt);
				}
			}


input => input.hasFocus()


button => button.index !== this.options.cancelId


(e: KeyboardEvent) => {
				EventHelper.stop(e, true);
				const evt = new StandardKeyboardEvent(e);

				if (evt.equals(KeyCode.Escape)) {
					resolve({
						button: this.options.cancelId || 0,
						checkboxChecked: this.checkbox ? this.checkbox.checked : undefined
					});
				}
			}


(e: FocusEvent) => {
				if (!!e.relatedTarget && !!this.element) {
					if (!isAncestor(e.relatedTarget as HTMLElement, this.element)) {
						this.focusToReturn = e.relatedTarget as HTMLElement;

						if (e.target) {
							(e.target as HTMLElement).focus();
							EventHelper.stop(e, true);
						}
					}
				}
			}


async () => {
				resolve({
					button: this.options.cancelId || 0,
					checkboxChecked: this.checkbox ? this.checkbox.checked : undefined
				});
			}


(value, index) => {
					if (value.index === 0) {
						buttonBar.buttons[index].focus();
					}
				}


button => button.style(style)


(button, index) => {
			buttonMap.push({ label: button, index });
		}


export interface IDialogInputOptions {
	readonly placeholder?: string;
	readonly type?: 'text' | 'password';
	readonly value?: string;
}


export interface IDialogOptions {
	readonly cancelId?: number;
	readonly detail?: string;
	readonly checkboxLabel?: string;
	readonly checkboxChecked?: boolean;
	readonly type?: 'none' | 'info' | 'error' | 'question' | 'warning' | 'pending';
	readonly inputs?: IDialogInputOptions[];
	readonly keyEventProcessor?: (event: StandardKeyboardEvent) => void;
	readonly renderBody?: (container: HTMLElement) => void;
	readonly icon?: Codicon;
}


export interface IDialogResult {
	readonly button: number;
	readonly checkboxChecked?: boolean;
	readonly values?: string[];
}


export interface IDialogStyles extends IButtonStyles, ISimpleCheckboxStyles {
	readonly dialogForeground?: Color;
	readonly dialogBackground?: Color;
	readonly dialogShadow?: Color;
	readonly dialogBorder?: Color;
	readonly errorIconForeground?: Color;
	readonly warningIconForeground?: Color;
	readonly infoIconForeground?: Color;
	readonly inputBackground?: Color;
	readonly inputForeground?: Color;
	readonly inputBorder?: Color;
}


interface ButtonMapEntry {
	readonly label: string;
	readonly index: number;
}


private getAriaLabel(): string {
		let typeLabel = nls.localize('dialogInfoMessage', 'Info');
		switch (this.options.type) {
			case 'error':
				nls.localize('dialogErrorMessage', 'Error');
				break;
			case 'warning':
				nls.localize('dialogWarningMessage', 'Warning');
				break;
			case 'pending':
				nls.localize('dialogPendingMessage', 'In Progress');
				break;
			case 'none':
			case 'info':
			case 'question':
			default:
				break;
		}

		return `${typeLabel}: ${this.message} ${this.options.detail || ''}`;
	}


updateMessage(message: string): void {
		this.messageDetailElement.innerText = message;
	}


async show(): Promise<IDialogResult> {
		this.focusToReturn = document.activeElement as HTMLElement;

		return new Promise<IDialogResult>((resolve) => {
			clearNode(this.buttonsContainer);

			const buttonBar = this.buttonBar = this._register(new ButtonBar(this.buttonsContainer));
			const buttonMap = this.rearrangeButtons(this.buttons, this.options.cancelId);

			// Handle button clicks
			buttonMap.forEach((entry, index) => {
				const button = this._register(buttonBar.addButton({ title: true }));
				button.label = mnemonicButtonLabel(buttonMap[index].label, true);

				this._register(button.onDidClick(e => {
					if (e) {
						EventHelper.stop(e);
					}

					resolve({
						button: buttonMap[index].index,
						checkboxChecked: this.checkbox ? this.checkbox.checked : undefined,
						values: this.inputs.length > 0 ? this.inputs.map(input => input.value) : undefined
					});
				}));
			});

			// Handle keyboard events gloably: Tab, Arrow-Left/Right
			this._register(domEvent(window, 'keydown', true)((e: KeyboardEvent) => {
				const evt = new StandardKeyboardEvent(e);

				if (evt.equals(KeyCode.Enter)) {

					// Enter in input field should OK the dialog
					if (this.inputs.some(input => input.hasFocus())) {
						EventHelper.stop(e);

						resolve({
							button: buttonMap.find(button => button.index !== this.options.cancelId)?.index ?? 0,
							checkboxChecked: this.checkbox ? this.checkbox.checked : undefined,
							values: this.inputs.length > 0 ? this.inputs.map(input => input.value) : undefined
						});
					}

					return; // leave default handling
				}

				if (evt.equals(KeyCode.Space)) {
					return; // leave default handling
				}

				let eventHandled = false;

				// Focus: Next / Previous
				if (evt.equals(KeyCode.Tab) || evt.equals(KeyCode.RightArrow) || evt.equals(KeyMod.Shift | KeyCode.Tab) || evt.equals(KeyCode.LeftArrow)) {

					// Build a list of focusable elements in their visual order
					const focusableElements: { focus: () => void }[] = [];
					let focusedIndex = -1;
					for (const input of this.inputs) {
						focusableElements.push(input);
						if (input.hasFocus()) {
							focusedIndex = focusableElements.length - 1;
						}
					}

					if (this.checkbox) {
						focusableElements.push(this.checkbox);
						if (this.checkbox.hasFocus()) {
							focusedIndex = focusableElements.length - 1;
						}
					}

					if (this.buttonBar) {
						for (const button of this.buttonBar.buttons) {
							focusableElements.push(button);
							if (button.hasFocus()) {
								focusedIndex = focusableElements.length - 1;
							}
						}
					}

					// Focus next element (with wrapping)
					if (evt.equals(KeyCode.Tab) || evt.equals(KeyCode.RightArrow)) {
						if (focusedIndex === -1) {
							focusedIndex = 0; // default to focus first element if none have focus
						}

						const newFocusedIndex = (focusedIndex + 1) % focusableElements.length;
						focusableElements[newFocusedIndex].focus();
					}

					// Focus previous element (with wrapping)
					else {
						if (focusedIndex === -1) {
							focusedIndex = focusableElements.length; // default to focus last element if none have focus
						}

						let newFocusedIndex = focusedIndex - 1;
						if (newFocusedIndex === -1) {
							newFocusedIndex = focusableElements.length - 1;
						}

						focusableElements[newFocusedIndex].focus();
					}

					eventHandled = true;
				}

				if (eventHandled) {
					EventHelper.stop(e, true);
				} else if (this.options.keyEventProcessor) {
					this.options.keyEventProcessor(evt);
				}
			}));

			this._register(domEvent(window, 'keyup', true)((e: KeyboardEvent) => {
				EventHelper.stop(e, true);
				const evt = new StandardKeyboardEvent(e);

				if (evt.equals(KeyCode.Escape)) {
					resolve({
						button: this.options.cancelId || 0,
						checkboxChecked: this.checkbox ? this.checkbox.checked : undefined
					});
				}
			}));

			// Detect focus out
			this._register(domEvent(this.element, 'focusout', false)((e: FocusEvent) => {
				if (!!e.relatedTarget && !!this.element) {
					if (!isAncestor(e.relatedTarget as HTMLElement, this.element)) {
						this.focusToReturn = e.relatedTarget as HTMLElement;

						if (e.target) {
							(e.target as HTMLElement).focus();
							EventHelper.stop(e, true);
						}
					}
				}
			}));

			const spinModifierClassName = 'codicon-modifier-spin';

			this.iconElement.classList.remove(...dialogErrorIcon.classNamesArray, ...dialogWarningIcon.classNamesArray, ...dialogInfoIcon.classNamesArray, ...Codicon.loading.classNamesArray, spinModifierClassName);

			if (this.options.icon) {
				this.iconElement.classList.add(...this.options.icon.classNamesArray);
			} else {
				switch (this.options.type) {
					case 'error':
						this.iconElement.classList.add(...dialogErrorIcon.classNamesArray);
						break;
					case 'warning':
						this.iconElement.classList.add(...dialogWarningIcon.classNamesArray);
						break;
					case 'pending':
						this.iconElement.classList.add(...Codicon.loading.classNamesArray, spinModifierClassName);
						break;
					case 'none':
					case 'info':
					case 'question':
					default:
						this.iconElement.classList.add(...dialogInfoIcon.classNamesArray);
						break;
				}
			}

			const actionBar = this._register(new ActionBar(this.toolbarContainer, {}));

			const action = this._register(new Action('dialog.close', nls.localize('dialogClose', "Close Dialog"), dialogCloseIcon.classNames, true, async () => {
				resolve({
					button: this.options.cancelId || 0,
					checkboxChecked: this.checkbox ? this.checkbox.checked : undefined
				});
			}));

			actionBar.push(action, { icon: true, label: false, });

			this.applyStyles();

			this.element.setAttribute('aria-label', this.getAriaLabel());
			show(this.element);

			// Focus first element (input or button)
			if (this.inputs.length > 0) {
				this.inputs[0].focus();
				this.inputs[0].select();
			} else {
				buttonMap.forEach((value, index) => {
					if (value.index === 0) {
						buttonBar.buttons[index].focus();
					}
				});
			}
		});
	}


private applyStyles() {
		if (this.styles) {
			const style = this.styles;

			const fgColor = style.dialogForeground;
			const bgColor = style.dialogBackground;
			const shadowColor = style.dialogShadow ? `0 0px 8px ${style.dialogShadow}` : '';
			const border = style.dialogBorder ? `1px solid ${style.dialogBorder}` : '';

			this.shadowElement.style.boxShadow = shadowColor;

			this.element.style.color = fgColor?.toString() ?? '';
			this.element.style.backgroundColor = bgColor?.toString() ?? '';
			this.element.style.border = border;

			if (this.buttonBar) {
				this.buttonBar.buttons.forEach(button => button.style(style));
			}

			if (this.checkbox) {
				this.checkbox.style(style);
			}

			if (fgColor && bgColor) {
				const messageDetailColor = fgColor.transparent(.9);
				this.messageDetailElement.style.color = messageDetailColor.makeOpaque(bgColor).toString();
			}

			let color;
			switch (this.options.type) {
				case 'error':
					color = style.errorIconForeground;
					break;
				case 'warning':
					color = style.warningIconForeground;
					break;
				default:
					color = style.infoIconForeground;
					break;
			}
			if (color) {
				this.iconElement.style.color = color.toString();
			}

			for (const input of this.inputs) {
				input.style(style);
			}
		}
	}


style(style: IDialogStyles): void {
		this.styles = style;

		this.applyStyles();
	}


override dispose(): void {
		super.dispose();

		if (this.modalElement) {
			this.modalElement.remove();
			this.modalElement = undefined;
		}

		if (this.focusToReturn && isAncestor(this.focusToReturn, document.body)) {
			this.focusToReturn.focus();
			this.focusToReturn = undefined;
		}
	}


private rearrangeButtons(buttons: Array<string>, cancelId: number | undefined): ButtonMapEntry[] {
		const buttonMap: ButtonMapEntry[] = [];

		// Maps each button to its current label and old index so that when we move them around it's not a problem
		buttons.forEach((button, index) => {
			buttonMap.push({ label: button, index });
		});

		// macOS/linux: reverse button order
		if (isMacintosh || isLinux) {
			if (cancelId !== undefined) {
				const cancelButton = buttonMap.splice(cancelId, 1)[0];
				buttonMap.reverse();
				buttonMap.splice(buttonMap.length - 1, 0, cancelButton);
			}
		}

		return buttonMap;
	}


(
        props: ResourceGridPropsInterface
): ReactElement => {

    const {
        children,
        className,
        emptyPlaceholder,
        isEmpty,
        isLoading,
        isPaginating,
        testId,
        wrapperClassName,
        ...rest
    } = props;

    const classes = classNames(
        "resource-grid",
        className
    );

    const wrapperClasses = classNames(
        "resource-grid-wrapper",
        wrapperClassName
    );

    return (
        <div className={ wrapperClasses } data-testid={ testId }>
            {
                isEmpty
                    ? emptyPlaceholder
                    : (
                        <Card.Group className={ classes } { ...rest }>
                            {
                                (isLoading && !isPaginating)
                                    ? <ContentLoader />
                                    : isPaginating
                                        ? <Loader>Loading...</Loader>


/**
 * Interface for the Resource Grid sub components.
 */
export interface ResourceGridSubComponentsInterface {
    Card: typeof ResourceGridCard;
}


/**
 * Interface for the Resource Grid component.
 */
export interface ResourceGridPropsInterface extends CardGroupProps, TestableComponentInterface,
    LoadableComponentInterface {

    /**
     * Empty placeholder component.
     */
    emptyPlaceholder?: ReactNode;
    /**
     * Is the list empty.
     */
    isEmpty?: boolean;
    /**
     * Is pagination in progress.
     */
    isPaginating?: boolean;
    /**
     * CSS classes for the wrapper.
     */
    wrapperClassName?: string;
}


export enum ReturnsConditionsCodeTypeEnum {
  Proprietary,
  FrenchBookTradeReturnsConditionsCode,
  BisacReturnableIndicatorCode,
  UkBookTradeReturnsConditionsCode,
  OnixReturnsConditionsCode
}


@Module({
  imports: [UsuarioModule],
  controllers: [],
  providers: [
    {
      provide: APP_FILTER,
      useClass: FiltroDeExcecaoHttp,
    },
    {
      provide: APP_INTERCEPTOR,
      useClass: ClassSerializerInterceptor,
    },
    {
      provide: APP_INTERCEPTOR,
      useClass: TransformaRespostaInterceptor,
    },
  ],
})
export class AppModule {}


/**
 * <p>Create an endpoint group for the specified listener for a custom routing accelerator.
 * 		An endpoint group is a collection of endpoints in one AWS
 * 		Region. </p>
 */
export class CreateCustomRoutingEndpointGroupCommand extends $Command<
  CreateCustomRoutingEndpointGroupCommandInput,
  CreateCustomRoutingEndpointGroupCommandOutput,
  GlobalAcceleratorClientResolvedConfig
> {
  // Start section: command_properties
  // End section: command_properties

  constructor(readonly input: CreateCustomRoutingEndpointGroupCommandInput) {
    // Start section: command_constructor
    super();
    // End section: command_constructor
  }

  /**
   * @internal
   */
  resolveMiddleware(
    clientStack: MiddlewareStack<ServiceInputTypes, ServiceOutputTypes>,
    configuration: GlobalAcceleratorClientResolvedConfig,
    options?: __HttpHandlerOptions
  ): Handler<CreateCustomRoutingEndpointGroupCommandInput, CreateCustomRoutingEndpointGroupCommandOutput> {
    this.middlewareStack.use(getSerdePlugin(configuration, this.serialize, this.deserialize));

    const stack = clientStack.concat(this.middlewareStack);

    const { logger } = configuration;
    const clientName = "GlobalAcceleratorClient";
    const commandName = "CreateCustomRoutingEndpointGroupCommand";
    const handlerExecutionContext: HandlerExecutionContext = {
      logger,
      clientName,
      commandName,
      inputFilterSensitiveLog: CreateCustomRoutingEndpointGroupRequest.filterSensitiveLog,
      outputFilterSensitiveLog: CreateCustomRoutingEndpointGroupResponse.filterSensitiveLog,
    };
    const { requestHandler } = configuration;
    return stack.resolve(
      (request: FinalizeHandlerArguments<any>) =>
        requestHandler.handle(request.request as __HttpRequest, options || {}),
      handlerExecutionContext
    );
  }

  private serialize(
    input: CreateCustomRoutingEndpointGroupCommandInput,
    context: __SerdeContext
  ): Promise<__HttpRequest> {
    return serializeAws_json1_1CreateCustomRoutingEndpointGroupCommand(input, context);
  }

  private deserialize(
    output: __HttpResponse,
    context: __SerdeContext
  ): Promise<CreateCustomRoutingEndpointGroupCommandOutput> {
    return deserializeAws_json1_1CreateCustomRoutingEndpointGroupCommand(output, context);
  }

  // Start section: command_body_extra
  // End section: command_body_extra
}


export type CreateCustomRoutingEndpointGroupCommandInput = CreateCustomRoutingEndpointGroupRequest;


export type CreateCustomRoutingEndpointGroupCommandOutput = CreateCustomRoutingEndpointGroupResponse & __MetadataBearer;


/**
   * @internal
   */
resolveMiddleware(
    clientStack: MiddlewareStack<ServiceInputTypes, ServiceOutputTypes>,
    configuration: GlobalAcceleratorClientResolvedConfig,
    options?: __HttpHandlerOptions
  ): Handler<CreateCustomRoutingEndpointGroupCommandInput, CreateCustomRoutingEndpointGroupCommandOutput> {
    this.middlewareStack.use(getSerdePlugin(configuration, this.serialize, this.deserialize));

    const stack = clientStack.concat(this.middlewareStack);

    const { logger } = configuration;
    const clientName = "GlobalAcceleratorClient";
    const commandName = "CreateCustomRoutingEndpointGroupCommand";
    const handlerExecutionContext: HandlerExecutionContext = {
      logger,
      clientName,
      commandName,
      inputFilterSensitiveLog: CreateCustomRoutingEndpointGroupRequest.filterSensitiveLog,
      outputFilterSensitiveLog: CreateCustomRoutingEndpointGroupResponse.filterSensitiveLog,
    };
    const { requestHandler } = configuration;
    return stack.resolve(
      (request: FinalizeHandlerArguments<any>) =>
        requestHandler.handle(request.request as __HttpRequest, options || {}),
      handlerExecutionContext
    );
  }


private serialize(
    input: CreateCustomRoutingEndpointGroupCommandInput,
    context: __SerdeContext
  ): Promise<__HttpRequest> {
    return serializeAws_json1_1CreateCustomRoutingEndpointGroupCommand(input, context);
  }


private deserialize(
    output: __HttpResponse,
    context: __SerdeContext
  ): Promise<CreateCustomRoutingEndpointGroupCommandOutput> {
    return deserializeAws_json1_1CreateCustomRoutingEndpointGroupCommand(output, context);
  }


() => {
  let component: UserDetailComponent;
  let fixture: ComponentFixture<UserDetailComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [UserDetailComponent],
      imports: [RouterTestingModule],
      providers: [{ provide: PersonService, useClass: MockPersonService }]
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(UserDetailComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should be created', () => {
    expect(component).toBeTruthy();
  });
}


() => {
    TestBed.configureTestingModule({
      declarations: [UserDetailComponent],
      imports: [RouterTestingModule],
      providers: [{ provide: PersonService, useClass: MockPersonService }]
    }).compileComponents();
  }


() => {
    fixture = TestBed.createComponent(UserDetailComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  }


class MockPersonService {
  public getById(id: String): Person {
    return mockPerson;
  }
}


public getById(id: String): Person {
    return mockPerson;
  }


() => {
      this.compute_indices()
      this.change.emit()
    }


() => {
      const fn = () => this.compute_indices()

      if (this.source != null) {
        this.connect(this.source.change, fn)

        if (this.source instanceof ColumnarDataSource) {
          this.connect(this.source.streaming, fn)
          this.connect(this.source.patching, fn)
        }
      }
    }


() => this.compute_indices()


() => {
        if (!initialized) {
          connect_listeners()
          initialized = true
        }
      }


(filter) => filter.compute_indices(this.source)


(indices) => indices != null


(i) => this.indices[i]


(i) => this.indices_map[i]


export class CDSView extends Model {
  properties: CDSView.Props

  constructor(attrs?: Partial<CDSView.Attrs>) {
    super(attrs)
  }

  static init_CDSView(): void {
    this.define<CDSView.Props>({
      filters: [ p.Array, [] ],
      source:  [ p.Instance  ],
    })

    this.internal({
      indices:     [ p.Array, [] ],
      indices_map: [ p.Any,   {} ],
    })
  }

  initialize(): void {
    super.initialize()
    this.compute_indices()
  }

  connect_signals(): void {
    super.connect_signals()

    this.connect(this.properties.filters.change, () => {
      this.compute_indices()
      this.change.emit()
    })

    const connect_listeners = () => {
      const fn = () => this.compute_indices()

      if (this.source != null) {
        this.connect(this.source.change, fn)

        if (this.source instanceof ColumnarDataSource) {
          this.connect(this.source.streaming, fn)
          this.connect(this.source.patching, fn)
        }
      }
    }

    let initialized = this.source != null

    if (initialized)
      connect_listeners()
    else {
      this.connect(this.properties.source.change, () => {
        if (!initialized) {
          connect_listeners()
          initialized = true
        }
      })
    }
  }

  compute_indices(): void {
    const indices = this.filters
      .map((filter) => filter.compute_indices(this.source))
      .filter((indices) => indices != null)

    if (indices.length > 0)
      this.indices = intersection.apply(this, indices)
    else if (this.source instanceof ColumnarDataSource)
      this.indices = this.source.get_indices()

    this.indices_map_to_subset()
  }

  indices_map_to_subset(): void {
    this.indices_map = {}
    for (let i = 0; i < this.indices.length; i++){
      this.indices_map[this.indices[i]] = i
    }
  }

  convert_selection_from_subset(selection_subset: Selection): Selection {
    const selection_full = new Selection()
    selection_full.update_through_union(selection_subset)
    const indices_1d = selection_subset.indices.map((i) => this.indices[i])
    selection_full.indices = indices_1d
    selection_full.image_indices = selection_subset.image_indices
    return selection_full
  }

  convert_selection_to_subset(selection_full: Selection): Selection {
    const selection_subset = new Selection()
    selection_subset.update_through_union(selection_full)
    const indices_1d = selection_full.indices.map((i) => this.indices_map[i])
    selection_subset.indices = indices_1d
    selection_subset.image_indices = selection_full.image_indices
    return selection_subset
  }

  convert_indices_from_subset(indices: number[]): number[] {
    return indices.map((i) => this.indices[i])
  }
}


export interface CDSView extends CDSView.Attrs {}


export type Attrs = p.AttrsOf<Props>


export type Props = Model.Props & {
    filters: p.Property<Filter[]>
    source: p.Property<ColumnarDataSource>
    indices: p.Property<number[]>
    indices_map: p.Property<{[key: string]: number}>
  }


static init_CDSView(): void {
    this.define<CDSView.Props>({
      filters: [ p.Array, [] ],
      source:  [ p.Instance  ],
    })

    this.internal({
      indices:     [ p.Array, [] ],
      indices_map: [ p.Any,   {} ],
    })
  }


initialize(): void {
    super.initialize()
    this.compute_indices()
  }


connect_signals(): void {
    super.connect_signals()

    this.connect(this.properties.filters.change, () => {
      this.compute_indices()
      this.change.emit()
    })

    const connect_listeners = () => {
      const fn = () => this.compute_indices()

      if (this.source != null) {
        this.connect(this.source.change, fn)

        if (this.source instanceof ColumnarDataSource) {
          this.connect(this.source.streaming, fn)
          this.connect(this.source.patching, fn)
        }
      }
    }

    let initialized = this.source != null

    if (initialized)
      connect_listeners()
    else {
      this.connect(this.properties.source.change, () => {
        if (!initialized) {
          connect_listeners()
          initialized = true
        }
      })
    }
  }


compute_indices(): void {
    const indices = this.filters
      .map((filter) => filter.compute_indices(this.source))
      .filter((indices) => indices != null)

    if (indices.length > 0)
      this.indices = intersection.apply(this, indices)
    else if (this.source instanceof ColumnarDataSource)
      this.indices = this.source.get_indices()

    this.indices_map_to_subset()
  }


indices_map_to_subset(): void {
    this.indices_map = {}
    for (let i = 0; i < this.indices.length; i++){
      this.indices_map[this.indices[i]] = i
    }
  }


convert_selection_from_subset(selection_subset: Selection): Selection {
    const selection_full = new Selection()
    selection_full.update_through_union(selection_subset)
    const indices_1d = selection_subset.indices.map((i) => this.indices[i])
    selection_full.indices = indices_1d
    selection_full.image_indices = selection_subset.image_indices
    return selection_full
  }


convert_selection_to_subset(selection_full: Selection): Selection {
    const selection_subset = new Selection()
    selection_subset.update_through_union(selection_full)
    const indices_1d = selection_full.indices.map((i) => this.indices_map[i])
    selection_subset.indices = indices_1d
    selection_subset.image_indices = selection_full.image_indices
    return selection_subset
  }


convert_indices_from_subset(indices: number[]): number[] {
    return indices.map((i) => this.indices[i])
  }


({ data }, ref) => {
    return (
      <AgGrid
        ref={ref}
        rowData={data}
        overlayNoRowsTemplate="No orders"
        defaultColDef={{ flex: 1, resizable: true }}


interface OrderListProps {
  data: Orders_party_orders[] | null;
}


/**
 *
Gets the status and details of an events detection job.

 * @example
 * Use a bare-bones client and the command you need to make an API call.
 * ```javascript
 * import { ComprehendClient, DescribeEventsDetectionJobCommand } from "@aws-sdk/client-comprehend"; // ES Modules import
 * // const { ComprehendClient, DescribeEventsDetectionJobCommand } = require("@aws-sdk/client-comprehend"); // CommonJS import
 * const client = new ComprehendClient(config);
 * const command = new DescribeEventsDetectionJobCommand(input);
 * const response = await client.send(command);
 * ```
 *
 * @see {@link DescribeEventsDetectionJobCommandInput} for command's `input` shape.
 * @see {@link DescribeEventsDetectionJobCommandOutput} for command's `response` shape.
 * @see {@link ComprehendClientResolvedConfig | config} for command's `input` shape.
 *
 */
export class DescribeEventsDetectionJobCommand extends $Command<
  DescribeEventsDetectionJobCommandInput,
  DescribeEventsDetectionJobCommandOutput,
  ComprehendClientResolvedConfig
> {
  // Start section: command_properties
  // End section: command_properties

  constructor(readonly input: DescribeEventsDetectionJobCommandInput) {
    // Start section: command_constructor
    super();
    // End section: command_constructor
  }

  /**
   * @internal
   */
  resolveMiddleware(
    clientStack: MiddlewareStack<ServiceInputTypes, ServiceOutputTypes>,
    configuration: ComprehendClientResolvedConfig,
    options?: __HttpHandlerOptions
  ): Handler<DescribeEventsDetectionJobCommandInput, DescribeEventsDetectionJobCommandOutput> {
    this.middlewareStack.use(getSerdePlugin(configuration, this.serialize, this.deserialize));

    const stack = clientStack.concat(this.middlewareStack);

    const { logger } = configuration;
    const clientName = "ComprehendClient";
    const commandName = "DescribeEventsDetectionJobCommand";
    const handlerExecutionContext: HandlerExecutionContext = {
      logger,
      clientName,
      commandName,
      inputFilterSensitiveLog: DescribeEventsDetectionJobRequest.filterSensitiveLog,
      outputFilterSensitiveLog: DescribeEventsDetectionJobResponse.filterSensitiveLog,
    };
    const { requestHandler } = configuration;
    return stack.resolve(
      (request: FinalizeHandlerArguments<any>) =>
        requestHandler.handle(request.request as __HttpRequest, options || {}),
      handlerExecutionContext
    );
  }

  private serialize(input: DescribeEventsDetectionJobCommandInput, context: __SerdeContext): Promise<__HttpRequest> {
    return serializeAws_json1_1DescribeEventsDetectionJobCommand(input, context);
  }

  private deserialize(
    output: __HttpResponse,
    context: __SerdeContext
  ): Promise<DescribeEventsDetectionJobCommandOutput> {
    return deserializeAws_json1_1DescribeEventsDetectionJobCommand(output, context);
  }

  // Start section: command_body_extra
  // End section: command_body_extra
}


export interface DescribeEventsDetectionJobCommandInput extends DescribeEventsDetectionJobRequest {}


export interface DescribeEventsDetectionJobCommandOutput extends DescribeEventsDetectionJobResponse, __MetadataBearer {}


/**
   * @internal
   */
resolveMiddleware(
    clientStack: MiddlewareStack<ServiceInputTypes, ServiceOutputTypes>,
    configuration: ComprehendClientResolvedConfig,
    options?: __HttpHandlerOptions
  ): Handler<DescribeEventsDetectionJobCommandInput, DescribeEventsDetectionJobCommandOutput> {
    this.middlewareStack.use(getSerdePlugin(configuration, this.serialize, this.deserialize));

    const stack = clientStack.concat(this.middlewareStack);

    const { logger } = configuration;
    const clientName = "ComprehendClient";
    const commandName = "DescribeEventsDetectionJobCommand";
    const handlerExecutionContext: HandlerExecutionContext = {
      logger,
      clientName,
      commandName,
      inputFilterSensitiveLog: DescribeEventsDetectionJobRequest.filterSensitiveLog,
      outputFilterSensitiveLog: DescribeEventsDetectionJobResponse.filterSensitiveLog,
    };
    const { requestHandler } = configuration;
    return stack.resolve(
      (request: FinalizeHandlerArguments<any>) =>
        requestHandler.handle(request.request as __HttpRequest, options || {}),
      handlerExecutionContext
    );
  }


private serialize(input: DescribeEventsDetectionJobCommandInput, context: __SerdeContext): Promise<__HttpRequest> {
    return serializeAws_json1_1DescribeEventsDetectionJobCommand(input, context);
  }


private deserialize(
    output: __HttpResponse,
    context: __SerdeContext
  ): Promise<DescribeEventsDetectionJobCommandOutput> {
    return deserializeAws_json1_1DescribeEventsDetectionJobCommand(output, context);
  }


(a, b) => b.lineNumber - a.lineNumber


export interface IValidatedEditOperation {
  sortIndex: number;
  identifier: ISingleEditOperationIdentifier;
  range: Range;
  rangeOffset: number;
  rangeLength: number;
  lines: string[];
  forceMoveMarkers: boolean;
  isAutoWhitespaceEdit: boolean;
}


/**
 * A processed string with its EOL resolved ready to be turned into an editor model.
 */
export interface ITextSource {
  /**
   * The text split into lines.
   */
  readonly lines: string[];
  /**
   * The BOM (leading character sequence of the file).
   */
  readonly BOM: string;
  /**
   * The end of line sequence.
   */
  readonly EOL: string;
  /**
   * The text contains Unicode characters classified as "R" or "AL".
   */
  readonly containsRTL: boolean;
  /**
   * The text contains only characters inside the ASCII range 32-126 or \t \r \n
   */
  readonly isBasicASCII: boolean;
}


private _constructLineStarts(): void {
    const eolLength = this._EOL.length;
    const linesLength = this._lines.length;
    const lineStartValues = new Uint32Array(linesLength);
    for (let i = 0; i < linesLength; i++) {
      lineStartValues[i] = this._lines[i].length + eolLength;
    }
    this._lineStarts = new PrefixSumComputer(lineStartValues);
  }


public equals(other: ITextBuffer): boolean {
    if (!(other instanceof LinesTextBuffer)) {
      return false;
    }
    if (this._BOM !== other._BOM) {
      return false;
    }
    if (this._EOL !== other._EOL) {
      return false;
    }
    if (this._lines.length !== other._lines.length) {
      return false;
    }
    for (let i = 0, len = this._lines.length; i < len; i++) {
      if (this._lines[i] !== other._lines[i]) {
        return false;
      }
    }
    return true;
  }


public mightContainRTL(): boolean {
    return this._mightContainRTL;
  }


public mightContainNonBasicASCII(): boolean {
    return this._mightContainNonBasicASCII;
  }


public getBOM(): string {
    return this._BOM;
  }


public getEOL(): string {
    return this._EOL;
  }


public getOffsetAt(lineNumber: number, column: number): number {
    return this._lineStarts.getAccumulatedValue(lineNumber - 2) + column - 1;
  }


public getPositionAt(offset: number): Position {
    offset = Math.floor(offset);
    offset = Math.max(0, offset);

    let out = this._lineStarts.getIndexOf(offset);

    let lineLength = this._lines[out.index].length;

    // Ensure we return a valid position
    return new Position(out.index + 1, Math.min(out.remainder + 1, lineLength + 1));
  }


public getRangeAt(offset: number, length: number): Range {
    const startResult = this._lineStarts.getIndexOf(offset);
    const startLineLength = this._lines[startResult.index].length;
    const startColumn = Math.min(startResult.remainder + 1, startLineLength + 1);

    const endResult = this._lineStarts.getIndexOf(offset + length);
    const endLineLength = this._lines[endResult.index].length;
    const endColumn = Math.min(endResult.remainder + 1, endLineLength + 1);

    return new Range(startResult.index + 1, startColumn, endResult.index + 1, endColumn);
  }


private _getEndOfLine(eol: EndOfLinePreference): string {
    switch (eol) {
      case EndOfLinePreference.LF:
        return '\n';
      case EndOfLinePreference.CRLF:
        return '\r\n';
      case EndOfLinePreference.TextDefined:
        return this.getEOL();
    }
    throw new Error('Unknown EOL preference');
  }


public getValueInRange(range: Range, eol: EndOfLinePreference): string {
    if (range.isEmpty()) {
      return '';
    }

    if (range.startLineNumber === range.endLineNumber) {
      return this._lines[range.startLineNumber - 1].substring(range.startColumn - 1, range.endColumn - 1);
    }

    const lineEnding = this._getEndOfLine(eol);
    const startLineIndex = range.startLineNumber - 1;
    const endLineIndex = range.endLineNumber - 1;
    let resultLines: string[] = [];

    resultLines.push(this._lines[startLineIndex].substring(range.startColumn - 1));
    for (let i = startLineIndex + 1; i < endLineIndex; i++) {
      resultLines.push(this._lines[i]);
    }
    resultLines.push(this._lines[endLineIndex].substring(0, range.endColumn - 1));

    return resultLines.join(lineEnding);
  }


public getValueLengthInRange(range: Range, eol: EndOfLinePreference): number {
    if (range.isEmpty()) {
      return 0;
    }

    if (range.startLineNumber === range.endLineNumber) {
      return (range.endColumn - range.startColumn);
    }

    let startOffset = this.getOffsetAt(range.startLineNumber, range.startColumn);
    let endOffset = this.getOffsetAt(range.endLineNumber, range.endColumn);
    return endOffset - startOffset;
  }


public getLineCount(): number {
    return this._lines.length;
  }


public getLinesContent(): string[] {
    return this._lines.slice(0);
  }


public getLineContent(lineNumber: number): string {
    return this._lines[lineNumber - 1];
  }


public getLineCharCode(lineNumber: number, index: number): number {
    return this._lines[lineNumber - 1].charCodeAt(index);
  }


public getLineLength(lineNumber: number): number {
    return this._lines[lineNumber - 1].length;
  }


public getLineFirstNonWhitespaceColumn(lineNumber: number): number {
    const result = firstNonWhitespaceIndex(this._lines[lineNumber - 1]);
    if (result === -1) {
      return 0;
    }
    return result + 1;
  }


public getLineLastNonWhitespaceColumn(lineNumber: number): number {
    const result = lastNonWhitespaceIndex(this._lines[lineNumber - 1]);
    if (result === -1) {
      return 0;
    }
    return result + 2;
  }


//#region Editing
public setEOL(newEOL: string): void {
    this._EOL = newEOL;
    this._constructLineStarts();
  }


private static _sortOpsAscending(a: IValidatedEditOperation, b: IValidatedEditOperation): number {
    let r = Range.compareRangesUsingEnds(a.range, b.range);
    if (r === 0) {
      return a.sortIndex - b.sortIndex;
    }
    return r;
  }


private static _sortOpsDescending(a: IValidatedEditOperation, b: IValidatedEditOperation): number {
    let r = Range.compareRangesUsingEnds(a.range, b.range);
    if (r === 0) {
      return b.sortIndex - a.sortIndex;
    }
    return -r;
  }


public applyEdits(rawOperations: IIdentifiedSingleEditOperation[], recordTrimAutoWhitespace: boolean): ApplyEditsResult {
    if (rawOperations.length === 0) {
      return new ApplyEditsResult([], [], []);
    }

    let mightContainRTL = this._mightContainRTL;
    let mightContainNonBasicASCII = this._mightContainNonBasicASCII;
    let canReduceOperations = true;

    let operations: IValidatedEditOperation[] = [];
    for (let i = 0; i < rawOperations.length; i++) {
      let op = rawOperations[i];
      if (canReduceOperations && op._isTracked) {
        canReduceOperations = false;
      }
      let validatedRange = op.range;
      if (!mightContainRTL && op.text) {
        // check if the new inserted text contains RTL
        mightContainRTL = containsRTL(op.text);
      }
      if (!mightContainNonBasicASCII && op.text) {
        mightContainNonBasicASCII = !isBasicASCII(op.text);
      }
      operations[i] = {
        sortIndex: i,
        identifier: op.identifier || null,
        range: validatedRange,
        rangeOffset: this.getOffsetAt(validatedRange.startLineNumber, validatedRange.startColumn),
        rangeLength: this.getValueLengthInRange(validatedRange, EndOfLinePreference.TextDefined),
        lines: op.text ? op.text.split(/\r\n|\r|\n/) : null,
        forceMoveMarkers: op.forceMoveMarkers || false,
        isAutoWhitespaceEdit: op.isAutoWhitespaceEdit || false
      };
    }

    // Sort operations ascending
    operations.sort(LinesTextBuffer._sortOpsAscending);

    for (let i = 0, count = operations.length - 1; i < count; i++) {
      let rangeEnd = operations[i].range.getEndPosition();
      let nextRangeStart = operations[i + 1].range.getStartPosition();

      if (nextRangeStart.isBefore(rangeEnd)) {
        // overlapping ranges
        throw new Error('Overlapping ranges are not allowed!');
      }
    }

    if (canReduceOperations) {
      operations = this._reduceOperations(operations);
    }

    // Delta encode operations
    let reverseRanges = LinesTextBuffer._getInverseEditRanges(operations);
    let newTrimAutoWhitespaceCandidates: { lineNumber: number, oldContent: string }[] = [];

    for (let i = 0; i < operations.length; i++) {
      let op = operations[i];
      let reverseRange = reverseRanges[i];

      if (recordTrimAutoWhitespace && op.isAutoWhitespaceEdit && op.range.isEmpty()) {
        // Record already the future line numbers that might be auto whitespace removal candidates on next edit
        for (let lineNumber = reverseRange.startLineNumber; lineNumber <= reverseRange.endLineNumber; lineNumber++) {
          let currentLineContent = '';
          if (lineNumber === reverseRange.startLineNumber) {
            currentLineContent = this.getLineContent(op.range.startLineNumber);
            if (firstNonWhitespaceIndex(currentLineContent) !== -1) {
              continue;
            }
          }
          newTrimAutoWhitespaceCandidates.push({ lineNumber: lineNumber, oldContent: currentLineContent });
        }
      }
    }

    let reverseOperations: IIdentifiedSingleEditOperation[] = [];
    for (let i = 0; i < operations.length; i++) {
      let op = operations[i];
      let reverseRange = reverseRanges[i];

      reverseOperations[i] = {
        identifier: op.identifier,
        range: reverseRange,
        text: this.getValueInRange(op.range, EndOfLinePreference.TextDefined),
        forceMoveMarkers: op.forceMoveMarkers
      };
    }

    this._mightContainRTL = mightContainRTL;
    this._mightContainNonBasicASCII = mightContainNonBasicASCII;

    const [rawContentChanges, contentChanges] = this._doApplyEdits(operations);

    let trimAutoWhitespaceLineNumbers: number[] = null;
    if (recordTrimAutoWhitespace && newTrimAutoWhitespaceCandidates.length > 0) {
      // sort line numbers auto whitespace removal candidates for next edit descending
      newTrimAutoWhitespaceCandidates.sort((a, b) => b.lineNumber - a.lineNumber);

      trimAutoWhitespaceLineNumbers = [];
      for (let i = 0, len = newTrimAutoWhitespaceCandidates.length; i < len; i++) {
        let lineNumber = newTrimAutoWhitespaceCandidates[i].lineNumber;
        if (i > 0 && newTrimAutoWhitespaceCandidates[i - 1].lineNumber === lineNumber) {
          // Do not have the same line number twice
          continue;
        }

        let prevContent = newTrimAutoWhitespaceCandidates[i].oldContent;
        let lineContent = this.getLineContent(lineNumber);

        if (lineContent.length === 0 || lineContent === prevContent || firstNonWhitespaceIndex(lineContent) !== -1) {
          continue;
        }

        trimAutoWhitespaceLineNumbers.push(lineNumber);
      }
    }

    return new ApplyEditsResult(
      reverseOperations,
      rawContentChanges,
      contentChanges,
    );
  }


/**
   * Transform operations such that they represent the same logic edit,
   * but that they also do not cause OOM crashes.
   */
private _reduceOperations(operations: IValidatedEditOperation[]): IValidatedEditOperation[] {
    if (operations.length < 1000) {
      // We know from empirical testing that a thousand edits work fine regardless of their shape.
      return operations;
    }

    // At one point, due to how events are emitted and how each operation is handled,
    // some operations can trigger a high ammount of temporary string allocations,
    // that will immediately get edited again.
    // e.g. a formatter inserting ridiculous ammounts of \n on a model with a single line
    // Therefore, the strategy is to collapse all the operations into a huge single edit operation
    return [this._toSingleEditOperation(operations)];
  }


_toSingleEditOperation(operations: IValidatedEditOperation[]): IValidatedEditOperation {
    let forceMoveMarkers = false,
      firstEditRange = operations[0].range,
      lastEditRange = operations[operations.length - 1].range,
      entireEditRange = new Range(firstEditRange.startLineNumber, firstEditRange.startColumn, lastEditRange.endLineNumber, lastEditRange.endColumn),
      lastEndLineNumber = firstEditRange.startLineNumber,
      lastEndColumn = firstEditRange.startColumn,
      result: string[] = [];

    for (let i = 0, len = operations.length; i < len; i++) {
      let operation = operations[i],
        range = operation.range;

      forceMoveMarkers = forceMoveMarkers || operation.forceMoveMarkers;

      // (1) -- Push old text
      for (let lineNumber = lastEndLineNumber; lineNumber < range.startLineNumber; lineNumber++) {
        if (lineNumber === lastEndLineNumber) {
          result.push(this._lines[lineNumber - 1].substring(lastEndColumn - 1));
        } else {
          result.push('\n');
          result.push(this._lines[lineNumber - 1]);
        }
      }

      if (range.startLineNumber === lastEndLineNumber) {
        result.push(this._lines[range.startLineNumber - 1].substring(lastEndColumn - 1, range.startColumn - 1));
      } else {
        result.push('\n');
        result.push(this._lines[range.startLineNumber - 1].substring(0, range.startColumn - 1));
      }

      // (2) -- Push new text
      if (operation.lines) {
        for (let j = 0, lenJ = operation.lines.length; j < lenJ; j++) {
          if (j !== 0) {
            result.push('\n');
          }
          result.push(operation.lines[j]);
        }
      }

      lastEndLineNumber = operation.range.endLineNumber;
      lastEndColumn = operation.range.endColumn;
    }

    return {
      sortIndex: 0,
      identifier: operations[0].identifier,
      range: entireEditRange,
      rangeOffset: this.getOffsetAt(entireEditRange.startLineNumber, entireEditRange.startColumn),
      rangeLength: this.getValueLengthInRange(entireEditRange, EndOfLinePreference.TextDefined),
      lines: result.join('').split('\n'),
      forceMoveMarkers: forceMoveMarkers,
      isAutoWhitespaceEdit: false
    };
  }


private _setLineContent(lineNumber: number, content: string, rawContentChanges: ModelRawChange[]): void {
    this._lines[lineNumber - 1] = content;
    this._lineStarts.changeValue(lineNumber - 1, content.length + this._EOL.length);
    rawContentChanges.push(new ModelRawLineChanged(lineNumber, content));
  }


private _doApplyEdits(operations: IValidatedEditOperation[]): [ModelRawChange[], IInternalModelContentChange[]] {

    // Sort operations descending
    operations.sort(LinesTextBuffer._sortOpsDescending);

    let rawContentChanges: ModelRawChange[] = [];
    let contentChanges: IInternalModelContentChange[] = [];

    for (let i = 0, len = operations.length; i < len; i++) {
      const op = operations[i];

      const startLineNumber = op.range.startLineNumber;
      const startColumn = op.range.startColumn;
      const endLineNumber = op.range.endLineNumber;
      const endColumn = op.range.endColumn;

      if (startLineNumber === endLineNumber && startColumn === endColumn && (!op.lines || op.lines.length === 0)) {
        // no-op
        continue;
      }

      const deletingLinesCnt = endLineNumber - startLineNumber;
      const insertingLinesCnt = (op.lines ? op.lines.length - 1 : 0);
      const editingLinesCnt = Math.min(deletingLinesCnt, insertingLinesCnt);

      for (let j = editingLinesCnt; j >= 0; j--) {
        const editLineNumber = startLineNumber + j;
        let editText = (op.lines ? op.lines[j] : '');

        if (editLineNumber === startLineNumber || editLineNumber === endLineNumber) {
          const editStartColumn = (editLineNumber === startLineNumber ? startColumn : 1);
          const editEndColumn = (editLineNumber === endLineNumber ? endColumn : this.getLineLength(editLineNumber) + 1);

          editText = (
            this._lines[editLineNumber - 1].substring(0, editStartColumn - 1)
            + editText
            + this._lines[editLineNumber - 1].substring(editEndColumn - 1)
          );
        }

        this._setLineContent(editLineNumber, editText, rawContentChanges);
      }

      if (editingLinesCnt < deletingLinesCnt) {
        // Must delete some lines

        const spliceStartLineNumber = startLineNumber + editingLinesCnt;
        const endLineRemains = this._lines[endLineNumber - 1].substring(endColumn - 1);

        // Reconstruct first line
        this._setLineContent(spliceStartLineNumber, this._lines[spliceStartLineNumber - 1] + endLineRemains, rawContentChanges);

        this._lines.splice(spliceStartLineNumber, endLineNumber - spliceStartLineNumber);
        this._lineStarts.removeValues(spliceStartLineNumber, endLineNumber - spliceStartLineNumber);

        rawContentChanges.push(new ModelRawLinesDeleted(spliceStartLineNumber + 1, endLineNumber));
      }

      if (editingLinesCnt < insertingLinesCnt) {
        // Must insert some lines

        const spliceLineNumber = startLineNumber + editingLinesCnt;
        let spliceColumn = (spliceLineNumber === startLineNumber ? startColumn : 1);
        if (op.lines) {
          spliceColumn += op.lines[editingLinesCnt].length;
        }

        // Split last line
        const leftoverLine = this._lines[spliceLineNumber - 1].substring(spliceColumn - 1);

        this._setLineContent(spliceLineNumber, this._lines[spliceLineNumber - 1].substring(0, spliceColumn - 1), rawContentChanges);

        // Lines in the middle
        let newLines: string[] = new Array<string>(insertingLinesCnt - editingLinesCnt);
        let newLinesLengths = new Uint32Array(insertingLinesCnt - editingLinesCnt);
        for (let j = editingLinesCnt + 1; j <= insertingLinesCnt; j++) {
          newLines[j - editingLinesCnt - 1] = op.lines[j];
          newLinesLengths[j - editingLinesCnt - 1] = op.lines[j].length + this._EOL.length;
        }
        newLines[newLines.length - 1] += leftoverLine;
        newLinesLengths[newLines.length - 1] += leftoverLine.length;
        this._lines = arrayInsert(this._lines, startLineNumber + editingLinesCnt, newLines);
        this._lineStarts.insertValues(startLineNumber + editingLinesCnt, newLinesLengths);

        rawContentChanges.push(new ModelRawLinesInserted(spliceLineNumber + 1, startLineNumber + insertingLinesCnt, newLines));
      }

      const contentChangeRange = new Range(startLineNumber, startColumn, endLineNumber, endColumn);
      const text = (op.lines ? op.lines.join(this.getEOL()) : '');
      contentChanges.push({
        range: contentChangeRange,
        rangeLength: op.rangeLength,
        text: text,
        lines: op.lines,
        rangeOffset: op.rangeOffset,
        forceMoveMarkers: op.forceMoveMarkers
      });
    }

    return [rawContentChanges, contentChanges];
  }


/**
   * Assumes `operations` are validated and sorted ascending
   */
public static _getInverseEditRanges(operations: IValidatedEditOperation[]): Range[] {
    let result: Range[] = [];

    let prevOpEndLineNumber: number;
    let prevOpEndColumn: number;
    let prevOp: IValidatedEditOperation = null;
    for (let i = 0, len = operations.length; i < len; i++) {
      let op = operations[i];

      let startLineNumber: number;
      let startColumn: number;

      if (prevOp) {
        if (prevOp.range.endLineNumber === op.range.startLineNumber) {
          startLineNumber = prevOpEndLineNumber;
          startColumn = prevOpEndColumn + (op.range.startColumn - prevOp.range.endColumn);
        } else {
          startLineNumber = prevOpEndLineNumber + (op.range.startLineNumber - prevOp.range.endLineNumber);
          startColumn = op.range.startColumn;
        }
      } else {
        startLineNumber = op.range.startLineNumber;
        startColumn = op.range.startColumn;
      }

      let resultRange: Range;

      if (op.lines && op.lines.length > 0) {
        // the operation inserts something
        let lineCount = op.lines.length;
        let firstLine = op.lines[0];
        let lastLine = op.lines[lineCount - 1];

        if (lineCount === 1) {
          // single line insert
          resultRange = new Range(startLineNumber, startColumn, startLineNumber, startColumn + firstLine.length);
        } else {
          // multi line insert
          resultRange = new Range(startLineNumber, startColumn, startLineNumber + lineCount - 1, lastLine.length + 1);
        }
      } else {
        // There is nothing to insert
        resultRange = new Range(startLineNumber, startColumn, startLineNumber, startColumn);
      }

      prevOpEndLineNumber = resultRange.endLineNumber;
      prevOpEndColumn = resultRange.endColumn;

      result.push(resultRange);
      prevOp = op;
    }

    return result;
  }


(e) => {
            this.loadConfigSettings();
        }


() => {
            this.markOutput();
        }


() => {
            this.clearOutput();
        }


async () => {
            let entryText: string = await vscode.window.showInputBox({
                placeHolder: 'Enter log include regex',
                value: this.includeRegex ? this.includeRegex.source : ''
            });
            if (entryText || entryText === '') {
                this.setIncludeFilter(entryText);
            }
        }


async () => {
            let entryText: string = await vscode.window.showInputBox({
                placeHolder: 'Enter log level regex',
                value: this.logLevelRegex ? this.logLevelRegex.source : ''
            });
            if (entryText || entryText === '') {
                this.setLevelFilter(entryText);
            }
        }


async () => {
            let entryText: string = await vscode.window.showInputBox({
                placeHolder: 'Enter log exclude regex',
                value: this.excludeRegex ? this.excludeRegex.source : ''
            });
            if (entryText || entryText === '') {
                this.setExcludeFilter(entryText);
            }
        }


async (compileError) => {
                    if (!errorsByPath[compileError.path]) {
                        errorsByPath[compileError.path] = [];
                    }
                    errorsByPath[compileError.path].push(compileError);
                }


(compileError) => {

                    const path: string = compileError.path;
                    const message: string = compileError.message;
                    const source: string = compileError.errorText;
                    const lineNumber: number = compileError.lineNumber;
                    const charStart: number = compileError.charStart;
                    const charEnd: number = compileError.charEnd;

                    diagnostics.push({
                        code: '',
                        message: message,
                        range: new vscode.Range(new vscode.Position(lineNumber, charStart), new vscode.Position(lineNumber, charEnd)),
                        severity: vscode.DiagnosticSeverity.Error,
                        source: source
                    });
                }


(line) => {
            if (line !== '') {
                if (!this.includeStackTraces) {
                    // filter out debugger noise
                    if (line.match(this.debugStartRegex)) {
                        console.log('start MicroDebugger block');
                        this.isInMicroDebugger = true;
                        this.isNextBreakpointSkipped = false;
                        line = 'Pausing for a breakpoint...';
                    } else if (this.isInMicroDebugger && line.match(this.debugEndRegex)) {
                        console.log('ended MicroDebugger block');
                        this.isInMicroDebugger = false;
                        if (this.isNextBreakpointSkipped) {
                            line = '\n**Was a bogus breakpoint** Skipping!\n';
                        } else {
                            line = null;
                        }
                    } else if (this.isInMicroDebugger) {
                        if (this.launchConfig.enableDebuggerAutoRecovery && line.startsWith('Break in ')) {
                            console.log('this block is a break: skipping it');
                            this.isNextBreakpointSkipped = true;
                        }
                        line = null;
                    }
                }
            }
            if (line) {
                const logLine = new LogLine(line, mustInclude);
                this.allLogLines.push(logLine);
                if (this.matchesFilter(logLine)) {
                    this.allLogLines.push(logLine);
                    this.addLogLineToOutput(logLine);
                    this.writeLogLineToLogfile(logLine.text);
                }
            }
        }


export class LogLine {
    constructor(
        public text: string,
        public isMustInclude: boolean
    ) {
    }
}


public onDidStartDebugSession() {
        this.isInMicroDebugger = false;
        this.isNextBreakpointSkipped = false;
        if (this.isClearingConsoleOnChannelStart) {
            this.clearOutput();
        }
    }


private loadConfigSettings() {
        let config: any = vscode.workspace.getConfiguration('brightscript') || {};
        this.includeStackTraces = (config.output || {}).includeStackTraces;
        this.isFocusingOutputOnLaunch = config?.output?.focusOnLaunch === false ? false : true;
        this.isClearingOutputOnLaunch = config?.output?.clearOnLaunch === false ? false : true;
        this.isClearingConsoleOnChannelStart = config?.output?.clearConsoleOnChannelStart === false ? false : true;
        this.hyperlinkFormat = (config.output || {}).hyperlinkFormat;
    }


public setLaunchConfig(launchConfig: BrightScriptLaunchConfiguration) {
        this.launchConfig = launchConfig;
    }


public onDidReceiveDebugSessionCustomEvent(e: any) {
        if (e.event === 'BSRendezvousEvent') {
            // No need to handle rendezvous type events
            return;
        }

        console.log('received event ' + e.event);
        if (e.event === 'BSLogOutputEvent') {
            this.appendLine(e.body);
        } else if (e.event === 'BSLaunchStartEvent') {
            this.isInMicroDebugger = false;
            this.isNextBreakpointSkipped = false;
            if (this.isFocusingOutputOnLaunch) {
                vscode.commands.executeCommand('workbench.action.focusPanel');
                this.outputChannel.show();
            }
            if (this.isClearingOutputOnLaunch) {
                this.clearOutput();
            }
        } else {
            let errorsByPath = {};
            if (e.body) {
                e.body.forEach(async (compileError) => {
                    if (!errorsByPath[compileError.path]) {
                        errorsByPath[compileError.path] = [];
                    }
                    errorsByPath[compileError.path].push(compileError);
                });
            }
            for (const path in errorsByPath) {
                if (errorsByPath.hasOwnProperty(path)) {
                    const errors = errorsByPath[path];
                    this.addDiagnosticForError(path, errors);
                }
            }
        }
    }


public async addDiagnosticForError(path: string, compileErrors: BrightScriptDebugCompileError[]) {

        //TODO get the actual folder
        let documentUri: vscode.Uri;
        let uri = vscode.Uri.file(path);
        let doc = await vscode.workspace.openTextDocument(uri); // calls back
        if (doc !== undefined) {
            documentUri = doc.uri;
        }
        // console.log("got " + documentUri);

        //debug crap - for some reason - using this URI works - using the one from the path does not :()
        // const document = vscode.window.activeTextEditor.document;
        // const currentDocumentUri = document.uri;
        // console.log("currentDocumentUri " + currentDocumentUri);
        if (documentUri !== undefined) {
            {
                let diagnostics: vscode.Diagnostic[] = [];
                compileErrors.forEach((compileError) => {

                    const path: string = compileError.path;
                    const message: string = compileError.message;
                    const source: string = compileError.errorText;
                    const lineNumber: number = compileError.lineNumber;
                    const charStart: number = compileError.charStart;
                    const charEnd: number = compileError.charEnd;

                    diagnostics.push({
                        code: '',
                        message: message,
                        range: new vscode.Range(new vscode.Position(lineNumber, charStart), new vscode.Position(lineNumber, charEnd)),
                        severity: vscode.DiagnosticSeverity.Error,
                        source: source
                    });
                });
                this.collection.set(documentUri, diagnostics);
            }
        }
    }


/**
     * Log output methods
     */
public appendLine(lineText: string, mustInclude: boolean = false): void {
        let lines = lineText.split('\n');
        lines.forEach((line) => {
            if (line !== '') {
                if (!this.includeStackTraces) {
                    // filter out debugger noise
                    if (line.match(this.debugStartRegex)) {
                        console.log('start MicroDebugger block');
                        this.isInMicroDebugger = true;
                        this.isNextBreakpointSkipped = false;
                        line = 'Pausing for a breakpoint...';
                    } else if (this.isInMicroDebugger && line.match(this.debugEndRegex)) {
                        console.log('ended MicroDebugger block');
                        this.isInMicroDebugger = false;
                        if (this.isNextBreakpointSkipped) {
                            line = '\n**Was a bogus breakpoint** Skipping!\n';
                        } else {
                            line = null;
                        }
                    } else if (this.isInMicroDebugger) {
                        if (this.launchConfig.enableDebuggerAutoRecovery && line.startsWith('Break in ')) {
                            console.log('this block is a break: skipping it');
                            this.isNextBreakpointSkipped = true;
                        }
                        line = null;
                    }
                }
            }
            if (line) {
                const logLine = new LogLine(line, mustInclude);
                this.allLogLines.push(logLine);
                if (this.matchesFilter(logLine)) {
                    this.allLogLines.push(logLine);
                    this.addLogLineToOutput(logLine);
                    this.writeLogLineToLogfile(logLine.text);
                }
            }
        });
    }


public writeLogLineToLogfile(text: string) {
        if (this.launchConfig?.logfilePath) {
            fsExtra.appendFileSync(this.launchConfig.logfilePath, text + '\n');
        }
    }


public addLogLineToOutput(logLine: LogLine) {
        const logLineNumber = this.displayedLogLines.length;
        if (this.matchesFilter(logLine)) {
            this.displayedLogLines.push(logLine);
            let match = this.pkgRegex.exec(logLine.text);
            if (match) {
                const pkgPath = match[1];
                const lineNumber = Number(match[2]);
                const filename = this.getFilename(pkgPath);
                const extension = pkgPath.substring(pkgPath.length - 4);
                let customText = this.getCustomLogText(pkgPath, filename, extension, Number(lineNumber), logLineNumber);
                const customLink = new CustomDocumentLink(logLineNumber, match.index, customText.length, pkgPath, lineNumber, filename);
                this.docLinkProvider.addCustomLink(customLink);
                let logText = logLine.text.substring(0, match.index) + customText + logLine.text.substring(match.index + match[0].length);
                this.outputChannel.appendLine(logText);
            } else {
                this.outputChannel.appendLine(logLine.text);
            }
        }
    }


public getFilename(pkgPath: string): string {
        const parts = pkgPath.split('/');
        let name = parts.length > 0 ? parts[parts.length - 1] : pkgPath;
        if (name.toLowerCase().endsWith('.xml') || name.toLowerCase().endsWith('.brs')) {
            name = name.substring(0, name.length - 4);
        }
        return name;
    }


public getCustomLogText(pkgPath: string, filename: string, extension: string, lineNumber: number, logLineNumber: number): string {
        switch (this.hyperlinkFormat) {
            case 'Full':
                return pkgPath + `(${lineNumber})`;
                break;
            case 'Short':
                return `#${logLineNumber}`;
                break;
            case 'Hidden':
                return ' ';
                break;
            case 'Filename':
                return `${filename}${extension}(${lineNumber})`;
                break;
            default:
                const isBrs = extension.toLowerCase() === '.brs';
                if (isBrs) {
                    const methodName = this.getMethodName(pkgPath, lineNumber);
                    if (methodName) {
                        return `${filename}.${methodName}(${lineNumber})`;
                    }
                }
                return pkgPath + `(${lineNumber})`;
                break;
        }
    }


public getMethodName(pkgPath: string, lineNumber: number): string | null {
        let fsPath = this.docLinkProvider.convertPkgPathToFsPath(pkgPath);
        const method = this.declarationProvider.getFunctionBeforeLine(fsPath, lineNumber);
        return method ? method.name : null;
    }


public matchesFilter(logLine: LogLine): boolean {
        return (logLine.isMustInclude || (
            (!this.logLevelRegex || this.logLevelRegex.test(logLine.text)))
            && (!this.includeRegex || this.includeRegex.test(logLine.text)))
            && (!this.excludeRegex || !this.excludeRegex.test(logLine.text)
            );
    }


public clearOutput(): any {
        this.markCount = 0;
        this.allLogLines = [];
        this.displayedLogLines = [];
        this.outputChannel.clear();
        this.collection.clear();
        this.docLinkProvider.resetCustomLinks();
    }


public setIncludeFilter(text: string): void {
        this.includeRegex = text && text.trim() !== '' ? new RegExp(text, 'i') : null;
        this.reFilterOutput();
    }


public setExcludeFilter(text: string): void {
        this.excludeRegex = text && text.trim() !== '' ? new RegExp(text, 'i') : null;
        this.reFilterOutput();
    }


public setLevelFilter(text: string): void {
        this.logLevelRegex = text && text.trim() !== '' ? new RegExp(text, 'i') : null;
        this.reFilterOutput();
    }


public reFilterOutput(): void {
        this.outputChannel.clear();
        this.docLinkProvider.resetCustomLinks();

        for (let i = 0; i < this.allLogLines.length - 1; i++) {
            let logLine = this.allLogLines[i];
            if (this.matchesFilter(logLine)) {
                this.addLogLineToOutput(logLine);
            }
        }
    }


public markOutput(): void {
        this.appendLine(`---------------------- MARK ${this.markCount} ----------------------`, true);
        this.markCount++;
    }


type => this.typeCreateForm.patchValue(type)


res => {
          let id = res['_id'];
          this.router.navigate(['settings/item/types/details', id]);
        }


@Component({
  selector: 'app-type-create',
  templateUrl: './type-create.component.html',
  styleUrls: ['./type-create.component.css']
})
export class TypeCreateComponent implements OnInit {
  type = {};
  typeCreateForm: FormGroup;
  pageType = 'Create';
  id = this.route.snapshot.params['id'];

  constructor(
    private router: Router,
    private route: ActivatedRoute,
    private api: ApiService,
    private fb: FormBuilder
  ) {
    this.createForm();
  }

  ngOnInit() {
    this.setupForm(this.id);
  }

  setupForm(id) {

    if(this.route.snapshot.data.update){
      this.pageType = 'Update';
      this.api.get('Type',id).subscribe(
        type => this.typeCreateForm.patchValue(type)
      );
    }
  }

  createForm(){
    this.typeCreateForm = this.fb.group({
      name: '',
      description: ''
    });
  }

  onFormSubmit(form: NgForm) {
    if (this.pageType === 'Create') {
      console.log('Creating', form)
      form = Object.assign(form, {name: form.name.trim().toLowerCase()});
      this.api.post('Type', form)
        .subscribe(res => {
          let id = res['_id'];
          this.router.navigate(['settings/item/types/details', id]);
        }, (err) => {
          console.log(err);
        });
    } else if (this.pageType === 'Update') {
      console.log('Updating', form)
      form = Object.assign(form, {name: form.name.trim().toLowerCase()});
      this.api.update('Type', this.id, form)
        .subscribe(res => {
          let id = res['_id'];
          this.router.navigate(['settings/item/types/details', id]);
        }, (err) => {
          console.log(err);
        });
    }
  }

}


ngOnInit() {
    this.setupForm(this.id);
  }


setupForm(id) {

    if(this.route.snapshot.data.update){
      this.pageType = 'Update';
      this.api.get('Type',id).subscribe(
        type => this.typeCreateForm.patchValue(type)
      );
    }
  }


createForm(){
    this.typeCreateForm = this.fb.group({
      name: '',
      description: ''
    });
  }


onFormSubmit(form: NgForm) {
    if (this.pageType === 'Create') {
      console.log('Creating', form)
      form = Object.assign(form, {name: form.name.trim().toLowerCase()});
      this.api.post('Type', form)
        .subscribe(res => {
          let id = res['_id'];
          this.router.navigate(['settings/item/types/details', id]);
        }, (err) => {
          console.log(err);
        });
    } else if (this.pageType === 'Update') {
      console.log('Updating', form)
      form = Object.assign(form, {name: form.name.trim().toLowerCase()});
      this.api.update('Type', this.id, form)
        .subscribe(res => {
          let id = res['_id'];
          this.router.navigate(['settings/item/types/details', id]);
        }, (err) => {
          console.log(err);
        });
    }
  }


() => {
  const s = new Spectral();
  s.addRules({
    'model-description': Object.assign(ruleset.rules['model-description'], {
      recommended: true,
      type: RuleType[ruleset.rules['model-description'].type],
    }),
  });

  test('validate a correct object', async () => {
    const results = await s.run({
      swagger: '2.0',
      paths: {},
      host: 'stoplight.io',
      definitions: {
        user: {
          description: 'this describes the user model',
        },
      },
    });
    expect(results.length).toEqual(0);
  });

  test('return errors if a definition is missing description', async () => {
    const results = await s.run({
      swagger: '2.0',
      paths: {},
      host: 'stoplight.io',
      definitions: { user: {} },
    });
    expect(results).toEqual([
      {
        code: 'model-description',
        message: 'Definition `description` must be present and non-empty string.',
        path: ['definitions', 'user', 'description'],
        range: {
          end: {
            character: 14,
            line: 5,
          },
          start: {
            character: 11,
            line: 5,
          },
        },
        severity: DiagnosticSeverity.Warning,
      },
    ]);
  });
}


async () => {
    const results = await s.run({
      swagger: '2.0',
      paths: {},
      host: 'stoplight.io',
      definitions: {
        user: {
          description: 'this describes the user model',
        },
      },
    });
    expect(results.length).toEqual(0);
  }


async () => {
    const results = await s.run({
      swagger: '2.0',
      paths: {},
      host: 'stoplight.io',
      definitions: { user: {} },
    });
    expect(results).toEqual([
      {
        code: 'model-description',
        message: 'Definition `description` must be present and non-empty string.',
        path: ['definitions', 'user', 'description'],
        range: {
          end: {
            character: 14,
            line: 5,
          },
          start: {
            character: 11,
            line: 5,
          },
        },
        severity: DiagnosticSeverity.Warning,
      },
    ]);
  }


/**
 * Dynamic interface to handle routes.
 */
export interface RouteInterface extends StaticRouteInterface {
    [ key: string ]: any;
}


/**
 * Interface for categorized routes.
 */
export interface CategorizedRouteInterface {
    [ key: string ]: RouteInterface[];
}


/**
 * Static route interface.
 */
export interface StaticRouteInterface {
    /**
     * Main category to put the rout under.
     */
    category?: string;
    /**
     * Component to be displayed.
     */
    component?: React.ReactNode | any;
    /**
     * Child routes.
     */
    children?: ChildRouteInterface[];
    /**
     * Exact match the route.
     */
    exact?: boolean;
    /**
     * Icon to be displayed on the side panel.
     */
    icon?: any;
    /**
     * A key to uniquely identify the route with
     */
    id: string;
    /**
     * Name to be displayed on the side panel.
     */
    name: string;
    /**
     * Router path.
     */
    path?: string;
    /**
     * If the route is protected or not.
     */
    protected: boolean;
    /**
     * Redirect path.
     */
    redirectTo?: string;
    /**
     * Should the item be displayed on the side panel.
     */
    showOnSidePanel: boolean;
    /**
     * Status of the feature.
     */
    featureStatus?: "new" | "alpha" | "beta" | string;
}


/**
 * Interface to handle child routes.
 * TODO: Remover this interface.
 */
export interface ChildRouteInterface extends RouteInterface {
    /**
     * Nesting level.
     */
    level?: number;
}


export type AwsKmsMrkAwareSymmetricDiscoveryKeyringNodeInput =
  AwsKmsMrkAwareSymmetricDiscoveryKeyringInput<KMS>


(query?: string): number | undefined =>
  query && typeof parseInt(query) === 'number' ? parseInt(query) : undefined


(rMap, [k, v]) => {
  rMap[v] = k;
  return rMap;
}


(apiServer: string) => (path?: string) =>
  path ? apiServer + path : apiServer


(path?: string) =>
  path ? apiServer + path : apiServer


export enum MODALS {
  SEARCH = 'modals/search',
  ADD_NETWORK = 'modals/add-network',
  UNLOCKING_SCHEDULE = 'modals/unlocking-schedule',
}


type ReverseMap<T extends Record<keyof T, any>> = {
  [V in T[keyof T]]: {
    [K in keyof T]: T[K] extends V ? K : never;
  }[keyof T];
};


export type AllModals = keyof typeof reverseMap;


export function getMaxImageFileSize(): number {
    return MAX_IMAGE_FILE_SIZE_BYTES;
}


export async function trainClassifier(
    project: DbObjects.Project,
): Promise<TrainingObjects.VisualClassifier>
{
    const training = await getTraining(project);

    try {
        const existingClassifiers = await store.getImageClassifiers(project.id);
        for (const existingClassifier of existingClassifiers) {
            await deleteClassifier(existingClassifier);
        }

        const credentials = await store.getBluemixCredentials(project.classid, 'visrec');
        const classifier = await createClassifier(project, credentials, training);

        return classifier;
    }
    finally {
        deleteTrainingFiles(training);
    }
}