/* *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0

THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.

See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */

// Typing for the jQuery library, version 1.10

/*
    Interface for the AJAX setting that will configure the AJAX request
*/
interface JQueryAjaxSettings {
    accepts?: any;
    async?: boolean;
    beforeSend? (jqXHR: JQueryXHR, settings: JQueryAjaxSettings): any;
    cache?: boolean;
    complete? (jqXHR: JQueryXHR, textStatus: string): any;
    contents?: { [key: string]: any; };
    contentType?: any;
    context?: any;
    converters?: { [key: string]: any; };
    crossDomain?: boolean;
    data?: any;
    dataFilter? (data: any, ty: any): any;
    dataType?: string;
    error? (jqXHR: JQueryXHR, textStatus: string, errorThrow: string): any;
    global?: boolean;
    headers?: { [key: string]: any; };
    ifModified?: boolean;
    isLocal?: boolean;
    jsonp?: string;
    jsonpCallback?: any;
    mimeType?: string;
    password?: string;
    processData?: boolean;
    scriptCharset?: string;
    statusCode?: { [key: string]: any; };
    success? (data: any, textStatus: string, jqXHR: JQueryXHR): any;
    timeout?: number;
    traditional?: boolean;
    type?: string;
    url?: string;
    username?: string;
    xhr?: any;
    xhrFields?: { [key: string]: any; };
}

/*
    Interface for the jqXHR object
*/
interface JQueryXHR extends XMLHttpRequest {
    overrideMimeType(): any;
}

/*
    Interface for the JQuery callback
*/
interface JQueryCallback {
    add(...callbacks: any[]): any;
    disable(): any;
    empty(): any;
    fire(...arguments: any[]): any;
    fired(): boolean;
    fireWith(context: any, ...args: any[]): any;
    has(callback: any): boolean;
    lock(): any;
    locked(): boolean;
    removed(...callbacks: any[]): any;
}

/*
    Interface for the JQuery promise, part of callbacks
*/
interface JQueryPromise {
    always(...alwaysCallbacks: any[]): JQueryDeferred;
    done(...doneCallbacks: any[]): JQueryDeferred;
    fail(...failCallbacks: any[]): JQueryDeferred;
    pipe(doneFilter?: (x: any) => any, failFilter?: (x: any) => any, progressFilter?: (x: any) => any): JQueryPromise;
    then(doneCallbacks: any, failCallbacks: any, progressCallbacks?: any): JQueryDeferred;
}

/*
    Interface for the JQuery deferred, part of callbacks
*/
interface JQueryDeferred extends JQueryPromise {
    notify(...args: any[]): JQueryDeferred;
    notifyWith(context: any, ...args: any[]): JQueryDeferred;

    progress(...progressCallbacks: any[]): JQueryDeferred;
    reject(...args: any[]): JQueryDeferred;
    rejectWith(context: any, ...args: any[]): JQueryDeferred;
    resolve(...args: any[]): JQueryDeferred;
    resolveWith(context: any, ...args: any[]): JQueryDeferred;
    state(): string;
    then(doneCallbacks: any, failCallbacks?: any, progressCallbacks?: any): JQueryDeferred;
}

/*
    Interface of the JQuery extension of the W3C event object
*/
interface JQueryEventObject extends Event {
    data: any;
    delegateTarget: Element;
    isDefaultPrevented(): boolean;
    isImmediatePropogationStopped(): boolean;
    isPropogationStopped(): boolean;
    namespace: string;
    preventDefault(): any;
    relatedTarget: Element;
    result: any;
    stopImmediatePropagation(): void;
    stopPropagation(): void;
    pageX: number;
    pageY: number;
    which: number;
    metaKey: any;
}

/*
    Collection of properties of the current browser
*/
interface JQueryBrowserInfo {
    safari: boolean;
    opera: boolean;
    msie: boolean;
    mozilla: boolean;
    version: string;
}

interface JQuerySupport {
    ajax?: boolean;
    boxModel?: boolean;
    changeBubbles?: boolean;
    checkClone?: boolean;
    checkOn?: boolean;
    cors?: boolean;
    cssFloat?: boolean;
    hrefNormalized?: boolean;
    htmlSerialize?: boolean;
    leadingWhitespace?: boolean;
    noCloneChecked?: boolean;
    noCloneEvent?: boolean;
    opacity?: boolean;
    optDisabled?: boolean;
    optSelected?: boolean;
    scriptEval? (): boolean;
    style?: boolean;
    submitBubbles?: boolean;
    tbody?: boolean;
}

interface JQueryTransport {
    send(headers: { [index: string]: string; }, completeCallback: (status: number, statusText: string, responses: { [dataType: string]: any; }, headers: string) => void): void;
    abort(): void;
}

/*
    Static members of jQuery (those on $ and jQuery themselves)
*/
interface JQueryStatic {

    // AJAX
    ajax(settings: JQueryAjaxSettings): JQueryXHR;
    ajax(url: string, settings: JQueryAjaxSettings): JQueryXHR;

    ajaxPrefilter(handler: (opts: any, originalOpts: any, jqXHR: JQueryXHR) => any): any;
    ajaxPrefilter(dataTypes: string, handler: (opts: any, originalOpts: any, jqXHR: JQueryXHR) => any): any;

    ajaxSetup(options: any): void;
    ajaxTransport(dataType: string, handler: (options: JQueryAjaxSettings, originalOptions: JQueryAjaxSettings, jqXHR: JQueryXHR) => JQueryTransport): void;

    get(url: string, data?: any, success?: any, dataType?: any): JQueryXHR;
    getJSON(url: string, data?: any, success?: any): JQueryXHR;
    getScript(url: string, success?: any): JQueryXHR;

    param(obj: any): string;
    param(obj: any, traditional: boolean): string;

    post(url: string, data?: any, success?: any, dataType?: any): JQueryXHR;

    // Callbacks
    Callbacks(flags: any): JQueryCallback;

    // Core
    holdReady(hold: boolean): any;

    (): JQuery;
    (selector: string, context?: any): JQuery;
    (element: Element): JQuery;
    (elementArray: Element[]): JQuery;
    (object: JQuery): JQuery;
    (func: Function): JQuery;
    (object: {}): JQuery;

    noConflict(removeAll?: boolean): Object;

    when(...deferreds: any[]): JQueryPromise;

    // CSS
    css(e: any, propertyName: string, value?: any): any;
    css(e: any, propertyName: any, value?: any): any;
    cssHooks: { [key: string]: any; };

    // Data
    data(element: Element, key: string, value: any): Object;

    dequeue(element: Element, queueName?: string): any;

    hasData(element: Element): boolean;

    queue(element: Element, queueName?: string): any[];
    queue(element: Element, queueName: string, newQueueOrCallback: any): JQuery;

    removeData(element: Element, name?: string): JQuery;

    // Deferred
    Deferred(beforeStart?: (deferred: JQueryDeferred) => any): JQueryDeferred;

    // Effects
    fx: { tick: () => void; interval: number; stop: () => void; speeds: { slow: number; fast: number; }; off: boolean; step: any; };

    // Events
    proxy(func: Function, context: any): any;
    proxy(context: any, name: string): any;

    // Internals
    error(message: any): void;

    // Miscellaneous
    expr: any;
    fn: any;  //TODO: Decide how we want to type this
    isReady: boolean;

    // Properties
    browser: JQueryBrowserInfo;
    support: JQuerySupport;

    // Utilities
    contains(container: Element, contained: Element): boolean;

    each(collection: any, callback: (indexInArray: any, valueOfElement: any) => any): any;

    extend(deep: boolean, target: any, ...objs: any[]): Object;
    extend(target: any, ...objs: any[]): Object;

    globalEval(code: string): any;

    grep(array: any[], func: any, invert: boolean): any[];

    inArray(value: any, array: any[], fromIndex?: number): number;

    isArray(obj: any): boolean;
    isEmptyObject(obj: any): boolean;
    isFunction(obj: any): boolean;
    isNumeric(value: any): boolean;
    isPlainObject(obj: any): boolean;
    isWindow(obj: any): boolean;
    isXMLDoc(node: Node): boolean;

    makeArray(obj: any): any[];

    map(array: any[], callback: (elementOfArray: any, indexInArray: any) => any): any[];

    merge(first: any[], second: any[]): any[];

    noop(): any;

    now(): number;

    parseHTML(data: string, context?: Element, keepScripts?: boolean): any[];
    parseJSON(json: string): any;

    //FIXME: This should return an XMLDocument
    parseXML(data: string): any;

    queue(element: Element, queueName: string, newQueue: any[]): JQuery;

    trim(str: string): string;

    type(obj: any): string;

    unique(arr: any[]): any[];
}

/*
    The jQuery instance members
*/
interface JQuery {
    // AJAX
    ajaxComplete(handler: any): JQuery;
    ajaxError(handler: (evt: any, xhr: any, opts: any) => any): JQuery;
    ajaxSend(handler: (evt: any, xhr: any, opts: any) => any): JQuery;
    ajaxStart(handler: () => any): JQuery;
    ajaxStop(handler: () => any): JQuery;
    ajaxSuccess(handler: (evt: any, xml: any, opts: any) => any): JQuery;

    serialize(): string;
    serializeArray(): any[];

    // Attributes
    addClass(classNames: string): JQuery;
    addClass(func: (index: any, currentClass: any) => JQuery): JQuery;

    attr(attributeName: string): string;
    attr(attributeName: string, func: (index: any, attr: any) => any): JQuery;
    attr(attributeName: string, value: any): JQuery;
    attr(map: { [key: string]: any; }): JQuery;

    hasClass(className: string): boolean;

    html(): string;
    html(htmlString: string): JQuery;

    prop(propertyName: string): any;
    prop(propertyName: string, func: (index: any, oldPropertyValue: any) => any): JQuery;
    prop(propertyName: string, value: any): JQuery;
    prop(map: any): JQuery;

    removeAttr(attributeName: any): JQuery;

    removeClass(func: (index: any, cls: any) => any): JQuery;
    removeClass(className?: string): JQuery;

    removeProp(propertyName: any): JQuery;

    toggleClass(func: (index: any, cls: any, swtch: any) => any): JQuery;
    toggleClass(swtch?: boolean): JQuery;
    toggleClass(className: any, swtch?: boolean): JQuery;

    val(): any;
    val(value: string[]): JQuery;
    val(value: string): JQuery;
    val(func: (index: any, value: any) => any): JQuery;

    // CSS
    css(propertyNames: any[]): string;
    css(propertyName: string): string;
    css(propertyName: string, value: any): JQuery;
    css(propertyName: any, value?: any): JQuery;

    height(): number;
    height(value: number): JQuery;
    height(func: (index: any, height: any) => any): JQuery;

    innerHeight(): number;
    innerWidth(): number;

    offset(): { top: number; left: number; };
    offset(func: (index: any, coords: any) => any): JQuery;
    offset(coordinates: any): JQuery;

    outerHeight(includeMargin?: boolean): number;
    outerWidth(includeMargin?: boolean): number;

    position(): { top: number; left: number; };

    scrollLeft(): number;
    scrollLeft(value: number): JQuery;

    scrollTop(): number;
    scrollTop(value: number): JQuery;

    width(): number;
    width(value: number): JQuery;
    width(func: (index: any, height: any) => any): JQuery;

    // Data
    clearQueue(queueName?: string): JQuery;

    data(key: string, value: any): JQuery;
    data(obj: { [key: string]: any; }): JQuery;
    data(key?: string): any;

    dequeue(queueName?: string): JQuery;

    queue(queueName?: string): any[];
    queue(queueName: string, newQueueOrCallback: any): JQuery;
    queue(newQueueOrCallback: any): JQuery;

    removeData(nameOrList?: any): JQuery;

    // Deferred
    promise(type?: any, target?: any): JQueryPromise;

    // Effects
    animate(properties: any, options: { duration?: any; easing?: string; complete?: Function; step?: Function; queue?: boolean; specialEasing?: any; }): JQuery;
    animate(properties: any, duration?: any, easing?: "linear", complete?: Function): JQuery;
    animate(properties: any, duration?: any, easing?: "swing", complete?: Function): JQuery;
    animate(properties: any, duration?: any, easing?: string, complete?: Function): JQuery;

    delay(duration: number, queueName?: string): JQuery;

    fadeIn(duration?: any, easing?: "linear", complete?: Function): JQuery;
    fadeIn(duration?: any, easing?: "swing", complete?: Function): JQuery;
    fadeIn(duration?: any, easing?: string, complete?: Function): JQuery;
    fadeIn(duration?: any, complete?: Function): JQuery;

    fadeOut(duration?: any, easing?: "linear", complete?: Function): JQuery;
    fadeOut(duration?: any, easing?: "swing", complete?: Function): JQuery;
    fadeOut(duration?: any, easing?: string, complete?: Function): JQuery;
    fadeOut(duration?: any, complete?: any): JQuery;

    fadeTo(duration: any, opacity: number, easing?: "linear", complete?: Function): JQuery;
    fadeTo(duration: any, opacity: number, easing?: "swing", complete?: Function): JQuery;
    fadeTo(duration: any, opacity: number, easing?: string, complete?: Function): JQuery;
    fadeTo(duration: any, opacity: number, complete?: Function): JQuery;

    fadeToggle(duration?: any, easing?: "linear", complete?: Function): JQuery;
    fadeToggle(duration?: any, easing?: "swing", complete?: Function): JQuery;
    fadeToggle(duration?: any, easing?: string, complete?: Function): JQuery;

    finish(queue?: string): JQuery;

    hide(duration?: any, easing?: "linear", callback?: Function): JQuery;
    hide(duration?: any, easing?: "swing", callback?: Function): JQuery;
    hide(duration?: any, easing?: string, callback?: Function): JQuery;
    hide(duration?: any, callback?: Function): JQuery;

    show(duration?: any, easing?: "linear", complete?: Function): JQuery;
    show(duration?: any, easing?: "swing", complete?: Function): JQuery;
    show(duration?: any, easing?: string, complete?: Function): JQuery;
    show(duration?: any, complete?: Function): JQuery;

    slideDown(duration?: any, easing?: "linear", complete?: Function): JQuery;
    slideDown(duration?: any, easing?: "swing", complete?: Function): JQuery;
    slideDown(duration?: any, easing?: string, complete?: Function): JQuery;
    slideDown(duration?: any, complete?: Function): JQuery;

    slideToggle(duration?: any, easing?: "linear", complete?: Function): JQuery;
    slideToggle(duration?: any, easing?: "swing", complete?: Function): JQuery;
    slideToggle(duration?: any, easing?: string, complete?: Function): JQuery;
    slideToggle(duration?: any, complete?: Function): JQuery;

    slideUp(duration?: any, easing?: "linear", complete?: Function): JQuery;
    slideUp(duration?: any, easing?: "swing", complete?: Function): JQuery;
    slideUp(duration?: any, easing?: string, complete?: Function): JQuery;
    slideUp(duration?: any, complete?: Function): JQuery;

    stop(clearQueue?: boolean, jumpToEnd?: boolean): JQuery;
    stop(queue?: any, clearQueue?: boolean, jumpToEnd?: boolean): JQuery;

    toggle(showOrHide: boolean): JQuery;
    toggle(duration?: any, easing?: "linear", complete?: Function): JQuery;
    toggle(duration?: any, easing?: "swing", complete?: Function): JQuery;
    toggle(duration?: any, easing?: string, complete?: Function): JQuery;
    toggle(duration?: any, complete?: Function): JQuery;

    // Events
    bind(eventType: string, preventBubble: boolean): JQuery;
    bind(eventType: string, eventData?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;
    bind(eventType: string, eventData: any, preventBubble: boolean): JQuery;
    bind(...events: any[]): JQuery;

    blur(handler: (eventObject: JQueryEventObject) => any): JQuery;
    blur(eventData?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;

    change(handler: (eventObject: JQueryEventObject) => any): JQuery;
    change(eventData?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;

    click(handler: (eventObject: JQueryEventObject) => any): JQuery;
    click(eventData?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;

    dblclick(handler: (eventObject: JQueryEventObject) => any): JQuery;
    dblclick(eventData?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;

    delegate(selector: any, eventType: string, handler: (eventObject: JQueryEventObject) => any): JQuery;

    focus(handler: (eventObject: JQueryEventObject) => any): JQuery;
    focus(eventData?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;

    focusin(handler: (eventObject: JQueryEventObject) => any): JQuery;
    focusin(eventData: any, handler: (eventObject: JQueryEventObject) => any): JQuery;

    focusout(handler: (eventObject: JQueryEventObject) => any): JQuery;
    focusout(eventData: any, handler: (eventObject: JQueryEventObject) => any): JQuery;

    hover(handlerIn: (eventObject: JQueryEventObject) => any, handlerOut: (eventObject: JQueryEventObject) => any): JQuery;
    hover(handlerInOut: (eventObject: JQueryEventObject) => any): JQuery;

    keydown(handler: (eventObject: JQueryEventObject) => any): JQuery;
    keydown(eventData?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;

    keypress(handler: (eventObject: JQueryEventObject) => any): JQuery;
    keypress(eventData?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;

    keyup(handler: (eventObject: JQueryEventObject) => any): JQuery;
    keyup(eventData?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;

    mousedown(handler: (eventObject: JQueryEventObject) => any): JQuery;
    mousedown(eventData: any, handler: (eventObject: JQueryEventObject) => any): JQuery;

    mouseevent(handler: (eventObject: JQueryEventObject) => any): JQuery;
    mouseevent(eventData: any, handler: (eventObject: JQueryEventObject) => any): JQuery;

    mouseenter(handler: (eventObject: JQueryEventObject) => any): JQuery;
    mouseenter(eventData: any, handler: (eventObject: JQueryEventObject) => any): JQuery;

    mouseleave(handler: (eventObject: JQueryEventObject) => any): JQuery;
    mouseleave(eventData: any, handler: (eventObject: JQueryEventObject) => any): JQuery;

    mousemove(handler: (eventObject: JQueryEventObject) => any): JQuery;
    mousemove(eventData: any, handler: (eventObject: JQueryEventObject) => any): JQuery;

    mouseout(handler: (eventObject: JQueryEventObject) => any): JQuery;
    mouseout(eventData: any, handler: (eventObject: JQueryEventObject) => any): JQuery;

    mouseover(handler: (eventObject: JQueryEventObject) => any): JQuery;
    mouseover(eventData: any, handler: (eventObject: JQueryEventObject) => any): JQuery;

    mouseup(handler: (eventObject: JQueryEventObject) => any): JQuery;
    mouseup(eventData: any, handler: (eventObject: JQueryEventObject) => any): JQuery;

    off(events?: string, selector?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;
    off(eventsMap: { [key: string]: any; }, selector?: any): JQuery;

    on(events: string, selector?: any, data?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;
    on(eventsMap: { [key: string]: any; }, selector?: any, data?: any): JQuery;

    one(events: string, selector?: any, data?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;
    one(eventsMap: { [key: string]: any; }, selector?: any, data?: any): JQuery;

    ready(handler: any): JQuery;

    resize(handler: (eventObject: JQueryEventObject) => any): JQuery;
    resize(eventData?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;

    scroll(handler: (eventObject: JQueryEventObject) => any): JQuery;
    scroll(eventData?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;

    select(handler: (eventObject: JQueryEventObject) => any): JQuery;
    select(eventData?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;

    submit(handler: (eventObject: JQueryEventObject) => any): JQuery;
    submit(eventData?: any, handler?: (eventObject: JQueryEventObject) => any): JQuery;

    trigger(eventType: string, ...extraParameters: any[]): JQuery;
    trigger(event: JQueryEventObject): JQuery;

    triggerHandler(eventType: string, ...extraParameters: any[]): Object;

    unbind(eventType?: string, handler?: (eventObject: JQueryEventObject) => any): JQuery;
    unbind(eventType: string, fls: boolean): JQuery;
    unbind(evt: any): JQuery;

    undelegate(): JQuery;
    undelegate(selector: any, eventType: string, handler?: (eventObject: JQueryEventObject) => any): JQuery;
    undelegate(selector: any, events: any): JQuery;
    undelegate(namespace: string): JQuery;

    // Internals
    context: Element;
    jquery: string;
    pushStack(elements: any[]): JQuery;
    pushStack(elements: any[], name: any, arguments: any): JQuery;

    // Manipulation
    after(func: (index: any) => any): JQuery;
    after(...content: any[]): JQuery;

    append(func: (index: any, html: any) => any): JQuery;
    append(...content: any[]): JQuery;

    appendTo(target: any): JQuery;

    before(func: (index: any) => any): JQuery;
    before(...content: any[]): JQuery;

    clone(withDataAndEvents?: boolean, deepWithDataAndEvents?: boolean): JQuery;

    detach(selector?: any): JQuery;

    empty(): JQuery;

    insertAfter(target: any): JQuery;
    insertBefore(target: any): JQuery;

    prepend(func: (index: any, html: any) => any): JQuery;
    prepend(...content: any[]): JQuery;

    prependTo(target: any): JQuery;

    remove(selector?: any): JQuery;

    replaceAll(target: any): JQuery;

    replaceWith(func: any): JQuery;

    text(textString: string): JQuery;
    text(): string;

    toArray(): any[];

    unwrap(): JQuery;

    wrap(func: (index: any) => any): JQuery;
    wrap(wrappingElement: any): JQuery;

    wrapAll(wrappingElement: any): JQuery;

    wrapInner(func: (index: any) => any): JQuery;
    wrapInner(wrappingElement: any): JQuery;

    // Miscellaneous
    each(func: (index: any, elem: Element) => any): JQuery;

    get(index?: number): any;

    index(selectorOrElement?: any): number;

    // Properties
    length: number;
    [x: number]: HTMLElement;

    // Traversing
    add(selector: string, context?: any): JQuery;
    add(html: string): JQuery;
    add(obj: JQuery): JQuery;
    add(...elements: any[]): JQuery;

    addBack(selector?: any): JQuery;

    children(selector?: any): JQuery;

    closest(selector: string): JQuery;
    closest(selector: string, context?: Element): JQuery;
    closest(obj: JQuery): JQuery;
    closest(element: any): JQuery;
    closest(selectors: any, context?: Element): any[];

    contents(): JQuery;

    end(): JQuery;

    eq(index: number): JQuery;

    filter(selector: string): JQuery;
    filter(func: (index: any) => any): JQuery;
    filter(obj: JQuery): JQuery;
    filter(element: any): JQuery;

    find(selector: string): JQuery;
    find(element: any): JQuery;
    find(obj: JQuery): JQuery;

    first(): JQuery;

    has(selector: string): JQuery;
    has(contained: Element): JQuery;

    is(selector: string): boolean;
    is(func: (index: any) => any): boolean;
    is(obj: JQuery): boolean;
    is(element: any): boolean;

    last(): JQuery;

    map(callback: (index: any, domElement: Element) => any): JQuery;

    next(selector?: string): JQuery;

    nextAll(selector?: string): JQuery;

    nextUntil(selector?: string, filter?: string): JQuery;
    nextUntil(element?: Element, filter?: string): JQuery;

    not(selector: string): JQuery;
    not(func: (index: any) => any): JQuery;
    not(obj: JQuery): JQuery;
    not(element: any): JQuery;

    offsetParent(): JQuery;

    parent(selector?: string): JQuery;

    parents(selector?: string): JQuery;

    parentsUntil(selector?: string, filter?: string): JQuery;
    parentsUntil(element?: Element, filter?: string): JQuery;

    prev(selector?: string): JQuery;

    prevAll(selector?: string): JQuery;

    prevUntil(selector?: string, filter?: string): JQuery;
    prevUntil(element?: Element, filter?: string): JQuery;

    siblings(selector?: string): JQuery;

    slice(start: number, end?: number): JQuery;
}

declare var jQuery: JQueryStatic;
declare var $: JQueryStatic;


// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Author: kenton@google.com (Kenton Varda)
//
// This is a dummy code generator plugin used by
// command_line_interface_unittest.

#include <string>
#include <stdlib.h>
#include <google/protobuf/compiler/plugin.h>
#include <google/protobuf/compiler/mock_code_generator.h>
#include <google/protobuf/stubs/strutil.h>

int main(int argc, char* argv[]) {
#ifdef _MSC_VER
  // Don't print a silly message or stick a modal dialog box in my face,
  // please.
  _set_abort_behavior(0, ~0);
#endif  // !_MSC_VER

  google::protobuf::compiler::MockCodeGenerator generator("test_plugin");
  return google::protobuf::compiler::PluginMain(argc, argv, &generator);
}


/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import * as assert from 'assert';
import { IUserDataSyncStoreService, SyncResource, UserDataSyncErrorCode, UserDataSyncStoreError, IUserDataSyncStoreManagementService, IUserDataSyncStore } from 'vs/platform/userDataSync/common/userDataSync';
import { UserDataSyncClient, UserDataSyncTestServer } from 'vs/platform/userDataSync/test/common/userDataSyncClient';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { IProductService, ConfigurationSyncStore } from 'vs/platform/product/common/productService';
import { isWeb } from 'vs/base/common/platform';
import { RequestsSession, UserDataSyncStoreService, UserDataSyncStoreManagementService } from 'vs/platform/userDataSync/common/userDataSyncStoreService';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IRequestService } from 'vs/platform/request/common/request';
import { newWriteableBufferStream, VSBuffer } from 'vs/base/common/buffer';
import { timeout } from 'vs/base/common/async';
import { NullLogService } from 'vs/platform/log/common/log';
import { Event } from 'vs/base/common/event';
import product from 'vs/platform/product/common/product';
import { IFileService } from 'vs/platform/files/common/files';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { URI } from 'vs/base/common/uri';

suite('UserDataSyncStoreManagementService', () => {
	const disposableStore = new DisposableStore();

	teardown(() => disposableStore.clear());

	test('test sync store is read from settings', async () => {
		const client = disposableStore.add(new UserDataSyncClient(new UserDataSyncTestServer()));
		await client.setUp();

		client.instantiationService.stub(IProductService, {
			_serviceBrand: undefined, ...product, ...{
				'configurationSync.store': undefined
			}
		});

		const configuredStore: ConfigurationSyncStore = {
			url: 'http://configureHost:3000',
			stableUrl: 'http://configureHost:3000',
			insidersUrl: 'http://configureHost:3000',
			canSwitch: false,
			authenticationProviders: { 'configuredAuthProvider': { scopes: [] } }
		};
		await client.instantiationService.get(IFileService).writeFile(client.instantiationService.get(IEnvironmentService).settingsResource, VSBuffer.fromString(JSON.stringify({
			'configurationSync.store': configuredStore
		})));
		await client.instantiationService.get(IConfigurationService).reloadConfiguration();

		const expected: IUserDataSyncStore = {
			url: URI.parse('http://configureHost:3000'),
			defaultUrl: URI.parse('http://configureHost:3000'),
			stableUrl: URI.parse('http://configureHost:3000'),
			insidersUrl: URI.parse('http://configureHost:3000'),
			canSwitch: false,
			authenticationProviders: [{ id: 'configuredAuthProvider', scopes: [] }]
		};

		const testObject: IUserDataSyncStoreManagementService = client.instantiationService.createInstance(UserDataSyncStoreManagementService);

		assert.equal(testObject.userDataSyncStore?.url.toString(), expected.url.toString());
		assert.equal(testObject.userDataSyncStore?.defaultUrl.toString(), expected.defaultUrl.toString());
		assert.deepEqual(testObject.userDataSyncStore?.authenticationProviders, expected.authenticationProviders);
	});

});

suite('UserDataSyncStoreService', () => {

	const disposableStore = new DisposableStore();

	teardown(() => disposableStore.clear());

	test('test read manifest for the first time', async () => {
		// Setup the client
		const target = new UserDataSyncTestServer();
		const client = disposableStore.add(new UserDataSyncClient(target));
		await client.setUp();
		const testObject = client.instantiationService.get(IUserDataSyncStoreService);
		const productService = client.instantiationService.get(IProductService);

		await testObject.manifest();

		assert.equal(target.requestsWithAllHeaders.length, 1);
		assert.equal(target.requestsWithAllHeaders[0].headers!['X-Client-Name'], `${productService.applicationName}${isWeb ? '-web' : ''}`);
		assert.equal(target.requestsWithAllHeaders[0].headers!['X-Client-Version'], productService.version);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-Machine-Id'], undefined);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'], undefined);
		assert.equal(target.requestsWithAllHeaders[0].headers!['X-User-Session-Id'], undefined);
	});

	test('test read manifest for the second time when session is not yet created', async () => {
		// Setup the client
		const target = new UserDataSyncTestServer();
		const client = disposableStore.add(new UserDataSyncClient(target));
		await client.setUp();
		const testObject = client.instantiationService.get(IUserDataSyncStoreService);

		await testObject.manifest();
		const machineSessionId = target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'];

		target.reset();
		await testObject.manifest();

		assert.equal(target.requestsWithAllHeaders.length, 1);
		assert.equal(target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'], machineSessionId);
		assert.equal(target.requestsWithAllHeaders[0].headers!['X-User-Session-Id'], undefined);
	});

	test('test session id header is not set in the first manifest request after session is created', async () => {
		// Setup the client
		const target = new UserDataSyncTestServer();
		const client = disposableStore.add(new UserDataSyncClient(target));
		await client.setUp();
		const testObject = client.instantiationService.get(IUserDataSyncStoreService);

		await testObject.manifest();
		const machineSessionId = target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'];
		await testObject.write(SyncResource.Settings, 'some content', null);

		target.reset();
		await testObject.manifest();

		assert.equal(target.requestsWithAllHeaders.length, 1);
		assert.equal(target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'], machineSessionId);
		assert.equal(target.requestsWithAllHeaders[0].headers!['X-User-Session-Id'], undefined);
	});

	test('test session id header is set from the second manifest request after session is created', async () => {
		// Setup the client
		const target = new UserDataSyncTestServer();
		const client = disposableStore.add(new UserDataSyncClient(target));
		await client.setUp();
		const testObject = client.instantiationService.get(IUserDataSyncStoreService);

		await testObject.manifest();
		const machineSessionId = target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'];
		await testObject.write(SyncResource.Settings, 'some content', null);
		await testObject.manifest();

		target.reset();
		await testObject.manifest();

		assert.equal(target.requestsWithAllHeaders.length, 1);
		assert.equal(target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'], machineSessionId);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-User-Session-Id'], undefined);
	});

	test('test headers are send for write request', async () => {
		// Setup the client
		const target = new UserDataSyncTestServer();
		const client = disposableStore.add(new UserDataSyncClient(target));
		await client.setUp();
		const testObject = client.instantiationService.get(IUserDataSyncStoreService);

		await testObject.manifest();
		const machineSessionId = target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'];
		await testObject.write(SyncResource.Settings, 'some content', null);
		await testObject.manifest();
		await testObject.manifest();

		target.reset();
		await testObject.write(SyncResource.Settings, 'some content', null);

		assert.equal(target.requestsWithAllHeaders.length, 1);
		assert.equal(target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'], machineSessionId);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-User-Session-Id'], undefined);
	});

	test('test headers are send for read request', async () => {
		// Setup the client
		const target = new UserDataSyncTestServer();
		const client = disposableStore.add(new UserDataSyncClient(target));
		await client.setUp();
		const testObject = client.instantiationService.get(IUserDataSyncStoreService);

		await testObject.manifest();
		const machineSessionId = target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'];
		await testObject.write(SyncResource.Settings, 'some content', null);
		await testObject.manifest();
		await testObject.manifest();

		target.reset();
		await testObject.read(SyncResource.Settings, null);

		assert.equal(target.requestsWithAllHeaders.length, 1);
		assert.equal(target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'], machineSessionId);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-User-Session-Id'], undefined);
	});

	test('test headers are reset after session is cleared ', async () => {
		// Setup the client
		const target = new UserDataSyncTestServer();
		const client = disposableStore.add(new UserDataSyncClient(target));
		await client.setUp();
		const testObject = client.instantiationService.get(IUserDataSyncStoreService);

		await testObject.manifest();
		const machineSessionId = target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'];
		await testObject.write(SyncResource.Settings, 'some content', null);
		await testObject.manifest();
		await testObject.manifest();
		await testObject.clear();

		target.reset();
		await testObject.manifest();

		assert.equal(target.requestsWithAllHeaders.length, 1);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'], undefined);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'], machineSessionId);
		assert.equal(target.requestsWithAllHeaders[0].headers!['X-User-Session-Id'], undefined);
	});

	test('test old headers are sent after session is changed on server ', async () => {
		// Setup the client
		const target = new UserDataSyncTestServer();
		const client = disposableStore.add(new UserDataSyncClient(target));
		await client.setUp();
		const testObject = client.instantiationService.get(IUserDataSyncStoreService);

		await testObject.manifest();
		await testObject.write(SyncResource.Settings, 'some content', null);
		await testObject.manifest();
		target.reset();
		await testObject.manifest();
		const machineSessionId = target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'];
		const userSessionId = target.requestsWithAllHeaders[0].headers!['X-User-Session-Id'];
		await target.clear();

		// client 2
		const client2 = disposableStore.add(new UserDataSyncClient(target));
		await client2.setUp();
		const testObject2 = client2.instantiationService.get(IUserDataSyncStoreService);
		await testObject2.write(SyncResource.Settings, 'some content', null);

		target.reset();
		await testObject.manifest();

		assert.equal(target.requestsWithAllHeaders.length, 1);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'], undefined);
		assert.equal(target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'], machineSessionId);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-User-Session-Id'], undefined);
		assert.equal(target.requestsWithAllHeaders[0].headers!['X-User-Session-Id'], userSessionId);
	});

	test('test old headers are reset from second request after session is changed on server ', async () => {
		// Setup the client
		const target = new UserDataSyncTestServer();
		const client = disposableStore.add(new UserDataSyncClient(target));
		await client.setUp();
		const testObject = client.instantiationService.get(IUserDataSyncStoreService);

		await testObject.manifest();
		await testObject.write(SyncResource.Settings, 'some content', null);
		await testObject.manifest();
		target.reset();
		await testObject.manifest();
		const machineSessionId = target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'];
		const userSessionId = target.requestsWithAllHeaders[0].headers!['X-User-Session-Id'];
		await target.clear();

		// client 2
		const client2 = disposableStore.add(new UserDataSyncClient(target));
		await client2.setUp();
		const testObject2 = client2.instantiationService.get(IUserDataSyncStoreService);
		await testObject2.write(SyncResource.Settings, 'some content', null);

		await testObject.manifest();
		target.reset();
		await testObject.manifest();

		assert.equal(target.requestsWithAllHeaders.length, 1);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'], undefined);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'], machineSessionId);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-User-Session-Id'], undefined);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-User-Session-Id'], userSessionId);
	});

	test('test old headers are sent after session is cleared from another server ', async () => {
		// Setup the client
		const target = new UserDataSyncTestServer();
		const client = disposableStore.add(new UserDataSyncClient(target));
		await client.setUp();
		const testObject = client.instantiationService.get(IUserDataSyncStoreService);

		await testObject.manifest();
		await testObject.write(SyncResource.Settings, 'some content', null);
		await testObject.manifest();
		target.reset();
		await testObject.manifest();
		const machineSessionId = target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'];
		const userSessionId = target.requestsWithAllHeaders[0].headers!['X-User-Session-Id'];

		// client 2
		const client2 = disposableStore.add(new UserDataSyncClient(target));
		await client2.setUp();
		const testObject2 = client2.instantiationService.get(IUserDataSyncStoreService);
		await testObject2.clear();

		target.reset();
		await testObject.manifest();

		assert.equal(target.requestsWithAllHeaders.length, 1);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'], undefined);
		assert.equal(target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'], machineSessionId);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-User-Session-Id'], undefined);
		assert.equal(target.requestsWithAllHeaders[0].headers!['X-User-Session-Id'], userSessionId);
	});

	test('test headers are reset after session is cleared from another server ', async () => {
		// Setup the client
		const target = new UserDataSyncTestServer();
		const client = disposableStore.add(new UserDataSyncClient(target));
		await client.setUp();
		const testObject = client.instantiationService.get(IUserDataSyncStoreService);

		await testObject.manifest();
		await testObject.write(SyncResource.Settings, 'some content', null);
		await testObject.manifest();
		target.reset();
		await testObject.manifest();
		const machineSessionId = target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'];

		// client 2
		const client2 = disposableStore.add(new UserDataSyncClient(target));
		await client2.setUp();
		const testObject2 = client2.instantiationService.get(IUserDataSyncStoreService);
		await testObject2.clear();

		await testObject.manifest();
		target.reset();
		await testObject.manifest();

		assert.equal(target.requestsWithAllHeaders.length, 1);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'], undefined);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'], machineSessionId);
		assert.equal(target.requestsWithAllHeaders[0].headers!['X-User-Session-Id'], undefined);
	});

	test('test headers are reset after session is cleared from another server - started syncing again', async () => {
		// Setup the client
		const target = new UserDataSyncTestServer();
		const client = disposableStore.add(new UserDataSyncClient(target));
		await client.setUp();
		const testObject = client.instantiationService.get(IUserDataSyncStoreService);

		await testObject.manifest();
		await testObject.write(SyncResource.Settings, 'some content', null);
		await testObject.manifest();
		target.reset();
		await testObject.manifest();
		const machineSessionId = target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'];
		const userSessionId = target.requestsWithAllHeaders[0].headers!['X-User-Session-Id'];

		// client 2
		const client2 = disposableStore.add(new UserDataSyncClient(target));
		await client2.setUp();
		const testObject2 = client2.instantiationService.get(IUserDataSyncStoreService);
		await testObject2.clear();

		await testObject.manifest();
		await testObject.write(SyncResource.Settings, 'some content', null);
		await testObject.manifest();
		target.reset();
		await testObject.manifest();

		assert.equal(target.requestsWithAllHeaders.length, 1);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'], undefined);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-Machine-Session-Id'], machineSessionId);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-User-Session-Id'], userSessionId);
		assert.notEqual(target.requestsWithAllHeaders[0].headers!['X-User-Session-Id'], undefined);
	});

	test('test rate limit on server with retry after', async () => {
		const target = new UserDataSyncTestServer(1, 1);
		const client = disposableStore.add(new UserDataSyncClient(target));
		await client.setUp();
		const testObject = client.instantiationService.get(IUserDataSyncStoreService);

		await testObject.manifest();

		const promise = Event.toPromise(testObject.onDidChangeDonotMakeRequestsUntil);
		try {
			await testObject.manifest();
			assert.fail('should fail');
		} catch (e) {
			assert.ok(e instanceof UserDataSyncStoreError);
			assert.deepEqual((<UserDataSyncStoreError>e).code, UserDataSyncErrorCode.TooManyRequestsAndRetryAfter);
			await promise;
			assert.ok(!!testObject.donotMakeRequestsUntil);
		}
	});

	test('test donotMakeRequestsUntil is reset after retry time is finished', async () => {
		const client = disposableStore.add(new UserDataSyncClient(new UserDataSyncTestServer(1, 0.25)));
		await client.setUp();
		const testObject = client.instantiationService.get(IUserDataSyncStoreService);

		await testObject.manifest();
		try {
			await testObject.manifest();
		} catch (e) { }

		const promise = Event.toPromise(testObject.onDidChangeDonotMakeRequestsUntil);
		await timeout(300);
		await promise;
		assert.ok(!testObject.donotMakeRequestsUntil);
	});

	test('test donotMakeRequestsUntil is retrieved', async () => {
		const client = disposableStore.add(new UserDataSyncClient(new UserDataSyncTestServer(1, 1)));
		await client.setUp();
		const testObject = client.instantiationService.get(IUserDataSyncStoreService);

		await testObject.manifest();
		try {
			await testObject.manifest();
		} catch (e) { }

		const target = client.instantiationService.createInstance(UserDataSyncStoreService);
		assert.equal(target.donotMakeRequestsUntil?.getTime(), testObject.donotMakeRequestsUntil?.getTime());
	});

	test('test donotMakeRequestsUntil is checked and reset after retreived', async () => {
		const client = disposableStore.add(new UserDataSyncClient(new UserDataSyncTestServer(1, 0.25)));
		await client.setUp();
		const testObject = client.instantiationService.get(IUserDataSyncStoreService);

		await testObject.manifest();
		try {
			await testObject.manifest();
		} catch (e) { }

		await timeout(300);
		const target = client.instantiationService.createInstance(UserDataSyncStoreService);
		assert.ok(!target.donotMakeRequestsUntil);
	});

	test('test read resource request handles 304', async () => {
		// Setup the client
		const target = new UserDataSyncTestServer();
		const client = disposableStore.add(new UserDataSyncClient(target));
		await client.setUp();
		await client.sync();

		const testObject = client.instantiationService.get(IUserDataSyncStoreService);
		const expected = await testObject.read(SyncResource.Settings, null);
		const actual = await testObject.read(SyncResource.Settings, expected);

		assert.equal(actual, expected);
	});

});

suite('UserDataSyncRequestsSession', () => {

	const requestService: IRequestService = {
		_serviceBrand: undefined,
		async request() { return { res: { headers: {} }, stream: newWriteableBufferStream() }; },
		async resolveProxy() { return undefined; }
	};

	test('too many requests are thrown when limit exceeded', async () => {
		const testObject = new RequestsSession(1, 500, requestService, new NullLogService());
		await testObject.request({}, CancellationToken.None);

		try {
			await testObject.request({}, CancellationToken.None);
		} catch (error) {
			assert.ok(error instanceof UserDataSyncStoreError);
			assert.equal((<UserDataSyncStoreError>error).code, UserDataSyncErrorCode.LocalTooManyRequests);
			return;
		}
		assert.fail('Should fail with limit exceeded');
	});

	test('requests are handled after session is expired', async () => {
		const testObject = new RequestsSession(1, 500, requestService, new NullLogService());
		await testObject.request({}, CancellationToken.None);
		await timeout(600);
		await testObject.request({}, CancellationToken.None);
	});

	test('too many requests are thrown after session is expired', async () => {
		const testObject = new RequestsSession(1, 500, requestService, new NullLogService());
		await testObject.request({}, CancellationToken.None);
		await timeout(600);
		await testObject.request({}, CancellationToken.None);

		try {
			await testObject.request({}, CancellationToken.None);
		} catch (error) {
			assert.ok(error instanceof UserDataSyncStoreError);
			assert.equal((<UserDataSyncStoreError>error).code, UserDataSyncErrorCode.LocalTooManyRequests);
			return;
		}
		assert.fail('Should fail with limit exceeded');
	});

});


/*
Copyright 2015 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package net

import (
	"strings"

	"k8s.io/apimachinery/pkg/util/sets"
)

var validSchemes = sets.NewString("http", "https", "")

// SplitSchemeNamePort takes a string of the following forms:
//  * "<name>",                 returns "",        "<name>","",      true
//  * "<name>:<port>",          returns "",        "<name>","<port>",true
//  * "<scheme>:<name>:<port>", returns "<scheme>","<name>","<port>",true
//
// Name must be non-empty or valid will be returned false.
// Scheme must be "http" or "https" if specified
// Port is returned as a string, and it is not required to be numeric (could be
// used for a named port, for example).
func SplitSchemeNamePort(id string) (scheme, name, port string, valid bool) {
	parts := strings.Split(id, ":")
	switch len(parts) {
	case 1:
		name = parts[0]
	case 2:
		name = parts[0]
		port = parts[1]
	case 3:
		scheme = parts[0]
		name = parts[1]
		port = parts[2]
	default:
		return "", "", "", false
	}

	if len(name) > 0 && validSchemes.Has(scheme) {
		return scheme, name, port, true
	} else {
		return "", "", "", false
	}
}

// JoinSchemeNamePort returns a string that specifies the scheme, name, and port:
//  * "<name>"
//  * "<name>:<port>"
//  * "<scheme>:<name>:<port>"
// None of the parameters may contain a ':' character
// Name is required
// Scheme must be "", "http", or "https"
func JoinSchemeNamePort(scheme, name, port string) string {
	if len(scheme) > 0 {
		// Must include three segments to specify scheme
		return scheme + ":" + name + ":" + port
	}
	if len(port) > 0 {
		// Must include two segments to specify port
		return name + ":" + port
	}
	// Return name alone
	return name
}


NAME = 'router_redirect'

CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['router_redirect']


/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *     * Neither the name of The Linux Foundation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#ifndef __MM_QCAMERA_APP_H__
#define __MM_QCAMERA_APP_H__

#include <pthread.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <poll.h>

#include "mm_camera_interface.h"
#include "mm_jpeg_interface.h"

#define MM_QCAMERA_APP_INTERATION 1

#define MM_APP_MAX_DUMP_FRAME_NUM 1000

#define PREVIEW_BUF_NUM 7
#define VIDEO_BUF_NUM 7
#define ISP_PIX_BUF_NUM 9
#define STATS_BUF_NUM 4
#define RDI_BUF_NUM 8

#define DEFAULT_PREVIEW_FORMAT    CAM_FORMAT_YUV_420_NV21
#define DEFAULT_PREVIEW_WIDTH     800
#define DEFAULT_PREVIEW_HEIGHT    480
#define DEFAULT_PREVIEW_PADDING   CAM_PAD_TO_WORD
#define DEFAULT_VIDEO_FORMAT      CAM_FORMAT_YUV_420_NV12
#define DEFAULT_VIDEO_WIDTH       800
#define DEFAULT_VIDEO_HEIGHT      480
#define DEFAULT_VIDEO_PADDING     CAM_PAD_TO_2K
#define DEFAULT_SNAPSHOT_FORMAT   CAM_FORMAT_YUV_420_NV21
#define DEFAULT_SNAPSHOT_WIDTH    1280
#define DEFAULT_SNAPSHOT_HEIGHT   960
#define DEFAULT_SNAPSHOT_PADDING  CAM_PAD_TO_WORD

#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif

typedef enum {
    MM_CAMERA_OK,
    MM_CAMERA_E_GENERAL,
    MM_CAMERA_E_NO_MEMORY,
    MM_CAMERA_E_NOT_SUPPORTED,
    MM_CAMERA_E_INVALID_INPUT,
    MM_CAMERA_E_INVALID_OPERATION, /* 5 */
    MM_CAMERA_E_ENCODE,
    MM_CAMERA_E_BUFFER_REG,
    MM_CAMERA_E_PMEM_ALLOC,
    MM_CAMERA_E_CAPTURE_FAILED,
    MM_CAMERA_E_CAPTURE_TIMEOUT, /* 10 */
} mm_camera_status_type_t;

typedef enum {
    MM_CHANNEL_TYPE_ZSL,      /* preview, and snapshot main */
    MM_CHANNEL_TYPE_CAPTURE,  /* snapshot main, and postview */
    MM_CHANNEL_TYPE_PREVIEW,  /* preview only */
    MM_CHANNEL_TYPE_SNAPSHOT, /* snapshot main only */
    MM_CHANNEL_TYPE_VIDEO,    /* video only */
    MM_CHANNEL_TYPE_RDI,      /* rdi only */
    MM_CHANNEL_TYPE_MAX
} mm_camera_channel_type_t;

typedef struct {
    int                     fd;
    int                     main_ion_fd;
    struct ion_handle *     handle;
    uint32_t                size;
    void *                  data;
} mm_camera_app_meminfo_t;

typedef struct {
    mm_camera_buf_def_t buf;
    mm_camera_app_meminfo_t mem_info;
} mm_camera_app_buf_t;

typedef struct {
    uint32_t s_id;
    mm_camera_stream_config_t s_config;
    cam_frame_len_offset_t offset;
    uint8_t num_of_bufs;
    mm_camera_app_buf_t s_bufs[MM_CAMERA_MAX_NUM_FRAMES];
    mm_camera_app_buf_t s_info_buf;
} mm_camera_stream_t;

typedef struct {
    uint32_t ch_id;
    uint8_t num_streams;
    mm_camera_stream_t streams[MAX_STREAM_NUM_IN_BUNDLE];
} mm_camera_channel_t;

typedef struct {
    mm_camera_vtbl_t *cam;
    uint8_t num_channels;
    mm_camera_channel_t channels[MM_CHANNEL_TYPE_MAX];
    mm_jpeg_ops_t jpeg_ops;
    uint32_t jpeg_hdl;
    mm_camera_app_buf_t cap_buf;
    mm_camera_app_buf_t parm_buf;

    uint32_t current_jpeg_sess_id;
    mm_camera_super_buf_t* current_job_frames;
    uint32_t current_job_id;
    mm_camera_app_buf_t jpeg_buf;
} mm_camera_test_obj_t;

typedef struct {
  void *ptr;
  void* ptr_jpeg;

  uint8_t (*get_num_of_cameras) ();
  mm_camera_vtbl_t *(*mm_camera_open) (uint8_t camera_idx);
  uint32_t (*jpeg_open) (mm_jpeg_ops_t *ops);
} hal_interface_lib_t;

typedef struct {
    uint8_t num_cameras;
    hal_interface_lib_t hal_lib;
} mm_camera_app_t;

typedef int (*mm_app_test_t) (mm_camera_app_t *cam_apps);
typedef struct {
    mm_app_test_t f;
    int r;
} mm_app_tc_t;

extern int mm_app_unit_test_entry(mm_camera_app_t *cam_app);
extern int mm_app_dual_test_entry(mm_camera_app_t *cam_app);
extern void mm_app_dump_frame(mm_camera_buf_def_t *frame,
                              char *name,
                              char *ext,
                              int frame_idx);
extern void mm_app_dump_jpeg_frame(const void * data,
                                   uint32_t size,
                                   char* name,
                                   char* ext,
                                   int index);
extern int mm_camera_app_timedwait(uint8_t seconds);
extern int mm_camera_app_wait();
extern void mm_camera_app_done();
extern int mm_app_alloc_bufs(mm_camera_app_buf_t* app_bufs,
                             cam_frame_len_offset_t *frame_offset_info,
                             uint8_t num_bufs,
                             uint8_t is_streambuf);
extern int mm_app_release_bufs(uint8_t num_bufs,
                               mm_camera_app_buf_t* app_bufs);
extern int mm_app_stream_initbuf(cam_frame_len_offset_t *frame_offset_info,
                                 uint8_t *num_bufs,
                                 uint8_t **initial_reg_flag,
                                 mm_camera_buf_def_t **bufs,
                                 mm_camera_map_unmap_ops_tbl_t *ops_tbl,
                                 void *user_data);
extern int32_t mm_app_stream_deinitbuf(mm_camera_map_unmap_ops_tbl_t *ops_tbl,
                                       void *user_data);
extern int mm_app_cache_ops(mm_camera_app_meminfo_t *mem_info,
                            unsigned int cmd);
extern int32_t mm_app_stream_clean_invalidate_buf(int index, void *user_data);
extern int32_t mm_app_stream_invalidate_buf(int index, void *user_data);
extern int mm_app_open(mm_camera_app_t *cam_app,
                       uint8_t cam_id,
                       mm_camera_test_obj_t *test_obj);
extern int mm_app_close(mm_camera_test_obj_t *test_obj);
extern mm_camera_channel_t * mm_app_add_channel(
                                         mm_camera_test_obj_t *test_obj,
                                         mm_camera_channel_type_t ch_type,
                                         mm_camera_channel_attr_t *attr,
                                         mm_camera_buf_notify_t channel_cb,
                                         void *userdata);
extern int mm_app_del_channel(mm_camera_test_obj_t *test_obj,
                              mm_camera_channel_t *channel);
extern mm_camera_stream_t * mm_app_add_stream(mm_camera_test_obj_t *test_obj,
                                              mm_camera_channel_t *channel);
extern int mm_app_del_stream(mm_camera_test_obj_t *test_obj,
                             mm_camera_channel_t *channel,
                             mm_camera_stream_t *stream);
extern int mm_app_config_stream(mm_camera_test_obj_t *test_obj,
                                mm_camera_channel_t *channel,
                                mm_camera_stream_t *stream,
                                mm_camera_stream_config_t *config);
extern int mm_app_start_channel(mm_camera_test_obj_t *test_obj,
                                mm_camera_channel_t *channel);
extern int mm_app_stop_channel(mm_camera_test_obj_t *test_obj,
                               mm_camera_channel_t *channel);
extern mm_camera_channel_t *mm_app_get_channel_by_type(
                                    mm_camera_test_obj_t *test_obj,
                                    mm_camera_channel_type_t ch_type);

extern int mm_app_start_preview(mm_camera_test_obj_t *test_obj);
extern int mm_app_stop_preview(mm_camera_test_obj_t *test_obj);
extern int mm_app_start_preview_zsl(mm_camera_test_obj_t *test_obj);
extern int mm_app_stop_preview_zsl(mm_camera_test_obj_t *test_obj);
extern mm_camera_channel_t * mm_app_add_preview_channel(
                                mm_camera_test_obj_t *test_obj);
extern int mm_app_stop_and_del_channel(mm_camera_test_obj_t *test_obj,
                                       mm_camera_channel_t *channel);
extern mm_camera_channel_t * mm_app_add_snapshot_channel(
                                               mm_camera_test_obj_t *test_obj);
extern mm_camera_stream_t * mm_app_add_snapshot_stream(
                                                mm_camera_test_obj_t *test_obj,
                                                mm_camera_channel_t *channel,
                                                mm_camera_buf_notify_t stream_cb,
                                                void *userdata,
                                                uint8_t num_bufs,
                                                uint8_t num_burst);
extern int mm_app_start_record_preview(mm_camera_test_obj_t *test_obj);
extern int mm_app_stop_record_preview(mm_camera_test_obj_t *test_obj);
extern int mm_app_start_record(mm_camera_test_obj_t *test_obj);
extern int mm_app_stop_record(mm_camera_test_obj_t *test_obj);
extern int mm_app_start_live_snapshot(mm_camera_test_obj_t *test_obj);
extern int mm_app_stop_live_snapshot(mm_camera_test_obj_t *test_obj);
extern int mm_app_start_capture(mm_camera_test_obj_t *test_obj,
                                uint8_t num_snapshots);
extern int mm_app_stop_capture(mm_camera_test_obj_t *test_obj);
extern int mm_app_start_rdi(mm_camera_test_obj_t *test_obj, uint8_t num_burst);
extern int mm_app_stop_rdi(mm_camera_test_obj_t *test_obj);

#endif /* __MM_QCAMERA_APP_H__ */


/* Arduino SdFat Library
 * Copyright (C) 2009 by William Greiman
 *
 * This file is part of the Arduino SdFat Library
 *
 * This Library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This Library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with the Arduino SdFat Library.  If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include "Marlin.h"
#ifdef SDSUPPORT

#ifndef SdFatStructs_h
#define SdFatStructs_h

#define PACKED __attribute__((__packed__))
/**
 * \file
 * \brief FAT file structures
 */
/*
 * mostly from Microsoft document fatgen103.doc
 * http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx
 */
//------------------------------------------------------------------------------
/** Value for byte 510 of boot block or MBR */
uint8_t const BOOTSIG0 = 0X55;
/** Value for byte 511 of boot block or MBR */
uint8_t const BOOTSIG1 = 0XAA;
/** Value for bootSignature field int FAT/FAT32 boot sector */
uint8_t const EXTENDED_BOOT_SIG = 0X29;
//------------------------------------------------------------------------------
/**
 * \struct partitionTable
 * \brief MBR partition table entry
 *
 * A partition table entry for a MBR formatted storage device.
 * The MBR partition table has four entries.
 */
struct partitionTable {
          /**
           * Boot Indicator . Indicates whether the volume is the active
           * partition.  Legal values include: 0X00. Do not use for booting.
           * 0X80 Active partition.
           */
  uint8_t  boot;
          /**
            * Head part of Cylinder-head-sector address of the first block in
            * the partition. Legal values are 0-255. Only used in old PC BIOS.
            */
  uint8_t  beginHead;
          /**
           * Sector part of Cylinder-head-sector address of the first block in
           * the partition. Legal values are 1-63. Only used in old PC BIOS.
           */
  unsigned beginSector : 6;
           /** High bits cylinder for first block in partition. */
  unsigned beginCylinderHigh : 2;
          /**
           * Combine beginCylinderLow with beginCylinderHigh. Legal values
           * are 0-1023.  Only used in old PC BIOS.
           */
  uint8_t  beginCylinderLow;
          /**
           * Partition type. See defines that begin with PART_TYPE_ for
           * some Microsoft partition types.
           */
  uint8_t  type;
          /**
           * head part of cylinder-head-sector address of the last sector in the
           * partition.  Legal values are 0-255. Only used in old PC BIOS.
           */
  uint8_t  endHead;
          /**
           * Sector part of cylinder-head-sector address of the last sector in
           * the partition.  Legal values are 1-63. Only used in old PC BIOS.
           */
  unsigned endSector : 6;
           /** High bits of end cylinder */
  unsigned endCylinderHigh : 2;
          /**
           * Combine endCylinderLow with endCylinderHigh. Legal values
           * are 0-1023.  Only used in old PC BIOS.
           */
  uint8_t  endCylinderLow;
           /** Logical block address of the first block in the partition. */
  uint32_t firstSector;
           /** Length of the partition, in blocks. */
  uint32_t totalSectors;
} PACKED;
/** Type name for partitionTable */
typedef struct partitionTable part_t;
//------------------------------------------------------------------------------
/**
 * \struct masterBootRecord
 *
 * \brief Master Boot Record
 *
 * The first block of a storage device that is formatted with a MBR.
 */
struct masterBootRecord {
           /** Code Area for master boot program. */
  uint8_t  codeArea[440];
           /** Optional Windows NT disk signature. May contain boot code. */
  uint32_t diskSignature;
           /** Usually zero but may be more boot code. */
  uint16_t usuallyZero;
           /** Partition tables. */
  part_t   part[4];
           /** First MBR signature byte. Must be 0X55 */
  uint8_t  mbrSig0;
           /** Second MBR signature byte. Must be 0XAA */
  uint8_t  mbrSig1;
} PACKED;
/** Type name for masterBootRecord */
typedef struct masterBootRecord mbr_t;
//------------------------------------------------------------------------------
/**
 * \struct fat_boot
 *
 * \brief Boot sector for a FAT12/FAT16 volume.
 *
 */
struct fat_boot {
         /**
          * The first three bytes of the boot sector must be valid,
          * executable x 86-based CPU instructions. This includes a
          * jump instruction that skips the next nonexecutable bytes.
          */
  uint8_t jump[3];
         /**
          * This is typically a string of characters that identifies
          * the operating system that formatted the volume.
          */
  char    oemId[8];
          /**
           * The size of a hardware sector. Valid decimal values for this
           * field are 512, 1024, 2048, and 4096. For most disks used in
           * the United States, the value of this field is 512.
           */
  uint16_t bytesPerSector;
          /**
           * Number of sectors per allocation unit. This value must be a
           * power of 2 that is greater than 0. The legal values are
           * 1, 2, 4, 8, 16, 32, 64, and 128.  128 should be avoided.
           */
  uint8_t  sectorsPerCluster;
          /**
           * The number of sectors preceding the start of the first FAT,
           * including the boot sector. The value of this field is always 1.
           */
  uint16_t reservedSectorCount;
          /**
           * The number of copies of the FAT on the volume.
           * The value of this field is always 2.
           */
  uint8_t  fatCount;
          /**
           * For FAT12 and FAT16 volumes, this field contains the count of
           * 32-byte directory entries in the root directory. For FAT32 volumes,
           * this field must be set to 0. For FAT12 and FAT16 volumes, this
           * value should always specify a count that when multiplied by 32
           * results in a multiple of bytesPerSector.  FAT16 volumes should
           * use the value 512.
           */
  uint16_t rootDirEntryCount;
          /**
           * This field is the old 16-bit total count of sectors on the volume.
           * This count includes the count of all sectors in all four regions
           * of the volume. This field can be 0; if it is 0, then totalSectors32
           * must be nonzero.  For FAT32 volumes, this field must be 0. For
           * FAT12 and FAT16 volumes, this field contains the sector count, and
           * totalSectors32 is 0 if the total sector count fits
           * (is less than 0x10000).
           */
  uint16_t totalSectors16;
          /**
           * This dates back to the old MS-DOS 1.x media determination and is
           * no longer usually used for anything.  0xF8 is the standard value
           * for fixed (nonremovable) media. For removable media, 0xF0 is
           * frequently used. Legal values are 0xF0 or 0xF8-0xFF.
           */
  uint8_t  mediaType;
          /**
           * Count of sectors occupied by one FAT on FAT12/FAT16 volumes.
           * On FAT32 volumes this field must be 0, and sectorsPerFat32
           * contains the FAT size count.
           */
  uint16_t sectorsPerFat16;
           /** Sectors per track for interrupt 0x13. Not used otherwise. */
  uint16_t sectorsPerTrack;
           /** Number of heads for interrupt 0x13.  Not used otherwise. */
  uint16_t headCount;
          /**
           * Count of hidden sectors preceding the partition that contains this
           * FAT volume. This field is generally only relevant for media
           * visible on interrupt 0x13.
           */
  uint32_t hidddenSectors;
          /**
           * This field is the new 32-bit total count of sectors on the volume.
           * This count includes the count of all sectors in all four regions
           * of the volume.  This field can be 0; if it is 0, then
           * totalSectors16 must be nonzero.
           */
  uint32_t totalSectors32;
           /**
            * Related to the BIOS physical drive number. Floppy drives are
            * identified as 0x00 and physical hard disks are identified as
            * 0x80, regardless of the number of physical disk drives.
            * Typically, this value is set prior to issuing an INT 13h BIOS
            * call to specify the device to access. The value is only
            * relevant if the device is a boot device.
            */
  uint8_t  driveNumber;
           /** used by Windows NT - should be zero for FAT */
  uint8_t  reserved1;
           /** 0X29 if next three fields are valid */
  uint8_t  bootSignature;
           /**
            * A random serial number created when formatting a disk,
            * which helps to distinguish between disks.
            * Usually generated by combining date and time.
            */
  uint32_t volumeSerialNumber;
           /**
            * A field once used to store the volume label. The volume label
            * is now stored as a special file in the root directory.
            */
  char     volumeLabel[11];
           /**
            * A field with a value of either FAT, FAT12 or FAT16,
            * depending on the disk format.
            */
  char     fileSystemType[8];
           /** X86 boot code */
  uint8_t  bootCode[448];
           /** must be 0X55 */
  uint8_t  bootSectorSig0;
           /** must be 0XAA */
  uint8_t  bootSectorSig1;
} PACKED;
/** Type name for FAT Boot Sector */
typedef struct fat_boot fat_boot_t;
//------------------------------------------------------------------------------
/**
 * \struct fat32_boot
 *
 * \brief Boot sector for a FAT32 volume.
 *
 */
struct fat32_boot {
         /**
          * The first three bytes of the boot sector must be valid,
          * executable x 86-based CPU instructions. This includes a
          * jump instruction that skips the next nonexecutable bytes.
          */
  uint8_t jump[3];
         /**
          * This is typically a string of characters that identifies
          * the operating system that formatted the volume.
          */
  char    oemId[8];
          /**
           * The size of a hardware sector. Valid decimal values for this
           * field are 512, 1024, 2048, and 4096. For most disks used in
           * the United States, the value of this field is 512.
           */
  uint16_t bytesPerSector;
          /**
           * Number of sectors per allocation unit. This value must be a
           * power of 2 that is greater than 0. The legal values are
           * 1, 2, 4, 8, 16, 32, 64, and 128.  128 should be avoided.
           */
  uint8_t  sectorsPerCluster;
          /**
           * The number of sectors preceding the start of the first FAT,
           * including the boot sector. Must not be zero
           */
  uint16_t reservedSectorCount;
          /**
           * The number of copies of the FAT on the volume.
           * The value of this field is always 2.
           */
  uint8_t  fatCount;
          /**
           * FAT12/FAT16 only. For FAT32 volumes, this field must be set to 0.
           */
  uint16_t rootDirEntryCount;
          /**
           * For FAT32 volumes, this field must be 0.
           */
  uint16_t totalSectors16;
          /**
           * This dates back to the old MS-DOS 1.x media determination and is
           * no longer usually used for anything.  0xF8 is the standard value
           * for fixed (nonremovable) media. For removable media, 0xF0 is
           * frequently used. Legal values are 0xF0 or 0xF8-0xFF.
           */
  uint8_t  mediaType;
          /**
           * On FAT32 volumes this field must be 0, and sectorsPerFat32
           * contains the FAT size count.
           */
  uint16_t sectorsPerFat16;
           /** Sectors per track for interrupt 0x13. Not used otherwise. */
  uint16_t sectorsPerTrack;
           /** Number of heads for interrupt 0x13.  Not used otherwise. */
  uint16_t headCount;
          /**
           * Count of hidden sectors preceding the partition that contains this
           * FAT volume. This field is generally only relevant for media
           * visible on interrupt 0x13.
           */
  uint32_t hidddenSectors;
          /**
           * Contains the total number of sectors in the FAT32 volume.
           */
  uint32_t totalSectors32;
         /**
           * Count of sectors occupied by one FAT on FAT32 volumes.
           */
  uint32_t sectorsPerFat32;
          /**
           * This field is only defined for FAT32 media and does not exist on
           * FAT12 and FAT16 media.
           * Bits 0-3 -- Zero-based number of active FAT.
           *             Only valid if mirroring is disabled.
           * Bits 4-6 -- Reserved.
           * Bit 7	-- 0 means the FAT is mirrored at runtime into all FATs.
	         *        -- 1 means only one FAT is active; it is the one referenced
	         *             in bits 0-3.
           * Bits 8-15 	-- Reserved.
           */
  uint16_t fat32Flags;
          /**
           * FAT32 version. High byte is major revision number.
           * Low byte is minor revision number. Only 0.0 define.
           */
  uint16_t fat32Version;
          /**
           * Cluster number of the first cluster of the root directory for FAT32.
           * This usually 2 but not required to be 2.
           */
  uint32_t fat32RootCluster;
          /**
           * Sector number of FSINFO structure in the reserved area of the
           * FAT32 volume. Usually 1.
           */
  uint16_t fat32FSInfo;
          /**
           * If nonzero, indicates the sector number in the reserved area
           * of the volume of a copy of the boot record. Usually 6.
           * No value other than 6 is recommended.
           */
  uint16_t fat32BackBootBlock;
          /**
           * Reserved for future expansion. Code that formats FAT32 volumes
           * should always set all of the bytes of this field to 0.
           */
  uint8_t  fat32Reserved[12];
           /**
            * Related to the BIOS physical drive number. Floppy drives are
            * identified as 0x00 and physical hard disks are identified as
            * 0x80, regardless of the number of physical disk drives.
            * Typically, this value is set prior to issuing an INT 13h BIOS
            * call to specify the device to access. The value is only
            * relevant if the device is a boot device.
            */
  uint8_t  driveNumber;
           /** used by Windows NT - should be zero for FAT */
  uint8_t  reserved1;
           /** 0X29 if next three fields are valid */
  uint8_t  bootSignature;
           /**
            * A random serial number created when formatting a disk,
            * which helps to distinguish between disks.
            * Usually generated by combining date and time.
            */
  uint32_t volumeSerialNumber;
           /**
            * A field once used to store the volume label. The volume label
            * is now stored as a special file in the root directory.
            */
  char     volumeLabel[11];
           /**
            * A text field with a value of FAT32.
            */
  char     fileSystemType[8];
           /** X86 boot code */
  uint8_t  bootCode[420];
           /** must be 0X55 */
  uint8_t  bootSectorSig0;
           /** must be 0XAA */
  uint8_t  bootSectorSig1;
} PACKED;
/** Type name for FAT32 Boot Sector */
typedef struct fat32_boot fat32_boot_t;
//------------------------------------------------------------------------------
/** Lead signature for a FSINFO sector */
uint32_t const FSINFO_LEAD_SIG = 0x41615252;
/** Struct signature for a FSINFO sector */
uint32_t const FSINFO_STRUCT_SIG = 0x61417272;
/**
 * \struct fat32_fsinfo
 *
 * \brief FSINFO sector for a FAT32 volume.
 *
 */
struct fat32_fsinfo {
           /** must be 0X52, 0X52, 0X61, 0X41 */
  uint32_t  leadSignature;
           /** must be zero */
  uint8_t  reserved1[480];
           /** must be 0X72, 0X72, 0X41, 0X61 */
  uint32_t  structSignature;
          /**
           * Contains the last known free cluster count on the volume.
           * If the value is 0xFFFFFFFF, then the free count is unknown
           * and must be computed. Any other value can be used, but is
           * not necessarily correct. It should be range checked at least
           * to make sure it is <= volume cluster count.
           */
  uint32_t freeCount;
          /**
           * This is a hint for the FAT driver. It indicates the cluster
           * number at which the driver should start looking for free clusters.
           * If the value is 0xFFFFFFFF, then there is no hint and the driver
           * should start looking at cluster 2.
           */
  uint32_t nextFree;
           /** must be zero */
  uint8_t  reserved2[12];
           /** must be 0X00, 0X00, 0X55, 0XAA */
  uint8_t  tailSignature[4];
} PACKED;
/** Type name for FAT32 FSINFO Sector */
typedef struct fat32_fsinfo fat32_fsinfo_t;
//------------------------------------------------------------------------------
// End Of Chain values for FAT entries
/** FAT12 end of chain value used by Microsoft. */
uint16_t const FAT12EOC = 0XFFF;
/** Minimum value for FAT12 EOC.  Use to test for EOC. */
uint16_t const FAT12EOC_MIN = 0XFF8;
/** FAT16 end of chain value used by Microsoft. */
uint16_t const FAT16EOC = 0XFFFF;
/** Minimum value for FAT16 EOC.  Use to test for EOC. */
uint16_t const FAT16EOC_MIN = 0XFFF8;
/** FAT32 end of chain value used by Microsoft. */
uint32_t const FAT32EOC = 0X0FFFFFFF;
/** Minimum value for FAT32 EOC.  Use to test for EOC. */
uint32_t const FAT32EOC_MIN = 0X0FFFFFF8;
/** Mask a for FAT32 entry. Entries are 28 bits. */
uint32_t const FAT32MASK = 0X0FFFFFFF;
//------------------------------------------------------------------------------
/**
 * \struct directoryEntry
 * \brief FAT short directory entry
 *
 * Short means short 8.3 name, not the entry size.
 *
 * Date Format. A FAT directory entry date stamp is a 16-bit field that is
 * basically a date relative to the MS-DOS epoch of 01/01/1980. Here is the
 * format (bit 0 is the LSB of the 16-bit word, bit 15 is the MSB of the
 * 16-bit word):
 *
 * Bits 9-15: Count of years from 1980, valid value range 0-127
 * inclusive (1980-2107).
 *
 * Bits 5-8: Month of year, 1 = January, valid value range 1-12 inclusive.
 *
 * Bits 0-4: Day of month, valid value range 1-31 inclusive.
 *
 * Time Format. A FAT directory entry time stamp is a 16-bit field that has
 * a granularity of 2 seconds. Here is the format (bit 0 is the LSB of the
 * 16-bit word, bit 15 is the MSB of the 16-bit word).
 *
 * Bits 11-15: Hours, valid value range 0-23 inclusive.
 *
 * Bits 5-10: Minutes, valid value range 0-59 inclusive.
 *
 * Bits 0-4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds).
 *
 * The valid time range is from Midnight 00:00:00 to 23:59:58.
 */
struct directoryEntry {
           /** Short 8.3 name.
            *
            * The first eight bytes contain the file name with blank fill.
            * The last three bytes contain the file extension with blank fill.
            */
  uint8_t  name[11];
          /** Entry attributes.
           *
           * The upper two bits of the attribute byte are reserved and should
           * always be set to 0 when a file is created and never modified or
           * looked at after that.  See defines that begin with DIR_ATT_.
           */
  uint8_t  attributes;
          /**
           * Reserved for use by Windows NT. Set value to 0 when a file is
           * created and never modify or look at it after that.
           */
  uint8_t  reservedNT;
          /**
           * The granularity of the seconds part of creationTime is 2 seconds
           * so this field is a count of tenths of a second and its valid
           * value range is 0-199 inclusive. (WHG note - seems to be hundredths)
           */
  uint8_t  creationTimeTenths;
           /** Time file was created. */
  uint16_t creationTime;
           /** Date file was created. */
  uint16_t creationDate;
          /**
           * Last access date. Note that there is no last access time, only
           * a date.  This is the date of last read or write. In the case of
           * a write, this should be set to the same date as lastWriteDate.
           */
  uint16_t lastAccessDate;
          /**
           * High word of this entry's first cluster number (always 0 for a
           * FAT12 or FAT16 volume).
           */
  uint16_t firstClusterHigh;
           /** Time of last write. File creation is considered a write. */
  uint16_t lastWriteTime;
           /** Date of last write. File creation is considered a write. */
  uint16_t lastWriteDate;
           /** Low word of this entry's first cluster number. */
  uint16_t firstClusterLow;
           /** 32-bit unsigned holding this file's size in bytes. */
  uint32_t fileSize;
} PACKED;
/**
 * \struct directoryVFATEntry
 * \brief VFAT long filename directory entry
 *
 * directoryVFATEntries are found in the same list as normal directoryEntry.
 * But have the attribute field set to DIR_ATT_LONG_NAME.
 *
 * Long filenames are saved in multiple directoryVFATEntries.
 * Each entry containing 13 UTF-16 characters.
 */
struct directoryVFATEntry {
  /**
   * Sequence number. Consists of 2 parts:
   *  bit 6:   indicates first long filename block for the next file
   *  bit 0-4: the position of this long filename block (first block is 1)
   */
  uint8_t  sequenceNumber;
  /** First set of UTF-16 characters */
  uint16_t name1[5];//UTF-16
  /** attributes (at the same location as in directoryEntry), always 0x0F */
  uint8_t  attributes;
  /** Reserved for use by Windows NT. Always 0. */
  uint8_t  reservedNT;
  /** Checksum of the short 8.3 filename, can be used to checked if the file system as modified by a not-long-filename aware implementation. */
  uint8_t  checksum;
  /** Second set of UTF-16 characters */
  uint16_t name2[6];//UTF-16
  /** firstClusterLow is always zero for longFilenames */
  uint16_t firstClusterLow;
  /** Third set of UTF-16 characters */
  uint16_t name3[2];//UTF-16
} PACKED;
//------------------------------------------------------------------------------
// Definitions for directory entries
//
/** Type name for directoryEntry */
typedef struct directoryEntry dir_t;
/** Type name for directoryVFATEntry */
typedef struct directoryVFATEntry vfat_t;
/** escape for name[0] = 0XE5 */
uint8_t const DIR_NAME_0XE5 = 0X05;
/** name[0] value for entry that is free after being "deleted" */
uint8_t const DIR_NAME_DELETED = 0XE5;
/** name[0] value for entry that is free and no allocated entries follow */
uint8_t const DIR_NAME_FREE = 0X00;
/** file is read-only */
uint8_t const DIR_ATT_READ_ONLY = 0X01;
/** File should hidden in directory listings */
uint8_t const DIR_ATT_HIDDEN = 0X02;
/** Entry is for a system file */
uint8_t const DIR_ATT_SYSTEM = 0X04;
/** Directory entry contains the volume label */
uint8_t const DIR_ATT_VOLUME_ID = 0X08;
/** Entry is for a directory */
uint8_t const DIR_ATT_DIRECTORY = 0X10;
/** Old DOS archive bit for backup support */
uint8_t const DIR_ATT_ARCHIVE = 0X20;
/** Test value for long name entry.  Test is
  (d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. */
uint8_t const DIR_ATT_LONG_NAME = 0X0F;
/** Test mask for long name entry */
uint8_t const DIR_ATT_LONG_NAME_MASK = 0X3F;
/** defined attribute bits */
uint8_t const DIR_ATT_DEFINED_BITS = 0X3F;
/** Directory entry is part of a long name
 * \param[in] dir Pointer to a directory entry.
 *
 * \return true if the entry is for part of a long name else false.
 */
static inline uint8_t DIR_IS_LONG_NAME(const dir_t* dir) {
  return (dir->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME;
}
/** Mask for file/subdirectory tests */
uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY);
/** Directory entry is for a file
 * \param[in] dir Pointer to a directory entry.
 *
 * \return true if the entry is for a normal file else false.
 */
static inline uint8_t DIR_IS_FILE(const dir_t* dir) {
  return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0;
}
/** Directory entry is for a subdirectory
 * \param[in] dir Pointer to a directory entry.
 *
 * \return true if the entry is for a subdirectory else false.
 */
static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) {
  return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY;
}
/** Directory entry is for a file or subdirectory
 * \param[in] dir Pointer to a directory entry.
 *
 * \return true if the entry is for a normal file or subdirectory else false.
 */
static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) {
  return (dir->attributes & DIR_ATT_VOLUME_ID) == 0;
}
#endif  // SdFatStructs_h

#endif


//  Estimote Fleet Management SDK
//  Copyright © 2015 Estimote. All rights reserved.

#import "ESTTelemetryInfo.h"

NS_ASSUME_NONNULL_BEGIN

/**
 * This class contains data read from telemetry packet from beacon device.
 */
DEPRECATED_MSG_ATTRIBUTE("Deprecated since 4.31.0.")
@interface ESTTelemetryInfoMotion : ESTTelemetryInfo

/**
 *  Accelerometer data related to X axis.
 */
@property (nonatomic, strong, readonly) NSNumber *accelerationX;

/**
 *  Accelerometer data related to Y axis.
 */
@property (nonatomic, strong, readonly) NSNumber *accelerationY;

/**
 *  Accelerometer data related to Z axis.
 */
@property (nonatomic, strong, readonly) NSNumber *accelerationZ;

/**
 * Duration of previous motion state.
 */
@property (nonatomic, strong, readonly) NSNumber *previousMotionStateDurationInSeconds;

/**
 * Duration of current motion state.
 */
@property (nonatomic, strong, readonly) NSNumber *currentMotionStateDurationInSeconds;

/**
 * Motion state of device. 0 means not moving, 1 means moving.
 */
@property (nonatomic, strong, readonly) NSNumber *motionState;

/**
 * Designated initializer of this class.
 *
 * @param accelerationX Data from beacons X axis, read from telemetry packet.
 * @param accelerationY Data from beacons Y axis, read from telemetry packet.
 * @param accelerationZ Data from beacons Z axis, read from telemetry packet.
 * @param previousMotionStateDurationInSeconds Duration of previous motion state, read from telemetry packet.
 * @param currentMotionStateDurationInSeconds Duration of current motion, read from telemetry packet.
 * @param motionState Current motion state, read from telemetry packet.
 * @param shortIdentifier Short identifier of device that sent telemetry packet
 *
 * @return Instance of this class.
 */
- (instancetype)   initWithAccelerationX:(NSNumber *)accelerationX
                           accelerationY:(NSNumber *)accelerationY
                           accelerationZ:(NSNumber *)accelerationZ
    previousMotionStateDurationInSeconds:(NSNumber *)previousMotionStateDurationInSeconds
     currentMotionStateDurationInSeconds:(NSNumber *)currentMotionStateDurationInSeconds
                             motionState:(NSNumber *)motionState
                         shortIdentifier:(NSString *)shortIdentifier;

@end

NS_ASSUME_NONNULL_END


# Join Token Suite

## Description

This suite verifies that:

- An agent can attest with a join token
- A join token vanity record can be used to register a workload
- A join token cannot be reused


/* Copyright (C) 2018-2020 The Manyverse Authors.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import {createElement as $, PureComponent} from 'react';
import {
  Linking,
  StyleSheet,
  Text,
  TextProperties,
  View,
  ViewProps,
} from 'react-native';
import {Palette} from '../global-styles/palette';
import {Dimensions} from '../global-styles/dimens';
import {Typography} from '../global-styles/typography';
import {GlobalEventBus} from '../drivers/eventbus';
import ZoomableImage from './ZoomableImage';
import AudioPlayer from './AudioPlayer';
const gemojiToEmoji = require('remark-gemoji-to-emoji');
const imagesToSsbServeBlobs = require('remark-images-to-ssb-serve-blobs');
const linkifyRegex = require('remark-linkify-regex');
const normalizeForReactNative = require('mdast-normalize-react-native');
const ReactMarkdown = require('react-markdown');
const Ref = require('ssb-ref');
const remark = require('remark');

const textProps: TextProperties = {
  selectable: true,
  textBreakStrategy: 'simple',
};

const styles = StyleSheet.create({
  text: {},

  heading1: {
    fontWeight: '700',
    color: Palette.text,
    fontSize: Typography.fontSizeLarger,
    lineHeight: Typography.lineHeightLarger,
    marginVertical: Dimensions.verticalSpaceSmall,
  },

  heading2: {
    fontWeight: '700',
    color: Palette.text,
    fontSize: Typography.fontSizeLarge,
    lineHeight: Typography.lineHeightLarge,
    marginVertical: Dimensions.verticalSpaceSmall,
  },

  heading3: {
    fontWeight: '700',
    color: Palette.text,
    fontSize: Typography.fontSizeBig,
    lineHeight: Typography.lineHeightBig,
    marginVertical: Dimensions.verticalSpaceSmall,
  },

  heading4: {
    fontWeight: '700',
    color: Palette.text,
    fontSize: Typography.fontSizeNormal,
    lineHeight: Typography.lineHeightNormal,
    marginVertical: Dimensions.verticalSpaceSmall,
  },

  heading5: {
    fontWeight: '700',
    color: Palette.text,
    fontSize: Typography.fontSizeSmall,
    lineHeight: Typography.lineHeightSmall,
    marginVertical: Dimensions.verticalSpaceSmall,
  },

  heading6: {
    fontWeight: '700',
    color: Palette.text,
    fontSize: Typography.fontSizeTiny,
    lineHeight: Typography.lineHeightTiny,
    marginVertical: Dimensions.verticalSpaceSmall,
  },

  paragraph: {
    flexWrap: 'wrap',
    flexDirection: 'row',
    alignItems: 'flex-start',
    justifyContent: 'flex-start',
    marginVertical: Dimensions.verticalSpaceSmall,
  },

  paragraphText: {
    flexWrap: 'wrap',
    overflow: 'visible',
    color: Palette.text,
    fontSize: Typography.fontSizeNormal,
    lineHeight: Typography.lineHeightNormal,
  },

  strong: {
    fontWeight: '700',
  },

  em: {
    fontStyle: 'italic',
  },

  strikethrough: {
    textDecorationLine: 'line-through',
  },

  link: {
    textDecorationLine: 'underline',
  },

  cypherlink: {
    color: Palette.textBrand,
    textDecorationLine: 'underline',
  },

  listItemText: {
    color: Palette.text,
    fontSize: Typography.fontSizeNormal,
    lineHeight: Typography.lineHeightNormal,
  },

  orderedBullet: {
    fontWeight: '700',
  },

  inlineCode: {
    backgroundColor: Palette.backgroundTextWeak,
    fontFamily: Typography.fontFamilyMonospace,
    color: Palette.textWeak,
  },

  codeBlock: {
    backgroundColor: Palette.backgroundTextWeak,
    marginVertical: Dimensions.verticalSpaceSmall,
    padding: Dimensions.verticalSpaceSmall,
  },

  codeText: {
    fontWeight: '400',
    color: Palette.textWeak,
    fontSize: Typography.fontSizeSmall,
    lineHeight: Typography.lineHeightSmall,
    fontFamily: Typography.fontFamilyMonospace,
  },

  blockquote: {
    backgroundColor: Palette.backgroundTextWeak,
    borderLeftWidth: 3,
    borderLeftColor: Palette.backgroundTextWeakStrong,
    marginVertical: Dimensions.verticalSpaceSmall,
    paddingLeft: Dimensions.horizontalSpaceSmall,
    paddingRight: 1,
  },

  horizontalLine: {
    backgroundColor: Palette.textLine,
    marginVertical: Dimensions.verticalSpaceSmall,
    height: 2,
  },
});

function makeRenderers(onLayout?: ViewProps['onLayout']) {
  const renderers = {
    root: (props: {children: any}) => $(View, {onLayout}, props.children),

    paragraph: (props: {children: any}) =>
      $(
        View,
        {style: styles.paragraph},
        $(Text, {...textProps, style: styles.paragraphText}, props.children),
      ),

    text: (props: {children: any}) =>
      $(Text, {...textProps, style: styles.text}, props.children),

    heading: (props: {children: any; level: 1 | 2 | 3 | 4 | 5 | 6}) =>
      $(
        Text,
        {...textProps, style: styles['heading' + props.level]},
        props.children,
      ),

    emphasis: (props: {children: any}) =>
      $(Text, {...textProps, style: styles.em}, props.children),

    strong: (props: {children: any}) =>
      $(Text, {...textProps, style: styles.strong}, props.children),

    link: (props: {children: any; href: string}) => {
      if (!props.href) return renderers.text(props);
      const isFeedCypherlink = Ref.isFeedId(props.href);
      const isMsgCypherlink = Ref.isMsgId(props.href);
      const isCypherlink = isFeedCypherlink || isMsgCypherlink;
      const isChildCypherlink =
        props.children.length === 1 &&
        (Ref.isFeedId(props.children[0]) || Ref.isMsgId(props.children[0]));
      return $(
        Text,
        {
          ...textProps,
          style: isCypherlink ? styles.cypherlink : styles.link,
          onPress: () => {
            if (isFeedCypherlink) {
              GlobalEventBus.dispatch({
                type: 'triggerFeedCypherlink',
                feedId: props.href,
              });
            } else if (isMsgCypherlink) {
              GlobalEventBus.dispatch({
                type: 'triggerMsgCypherlink',
                msgId: props.href,
              });
            } else {
              Linking.openURL(props.href);
            }
          },
        },
        isChildCypherlink
          ? [props.children[0].slice(0, 10) + '\u2026']
          : props.children,
      );
    },

    inlineCode: (props: {children: any}) =>
      $(Text, {...textProps, style: styles.inlineCode}, props.children),

    delete: (props: {children: any}) =>
      $(Text, {...textProps, style: styles.strikethrough}, props.children),

    blockquote: (props: {children: any}) =>
      $(View, {style: styles.blockquote}, props.children),

    code: (props: {value: string; language: string}) =>
      $(
        View,
        {style: styles.codeBlock},
        $(Text, {...textProps, style: styles.codeText}, props.value),
      ),

    thematicBreak: () => $(View, {style: styles.horizontalLine}),

    image: (props: {src: string; title?: string; alt?: string}) => {
      // Audio and video are recognized as images but their caption start with `audio:` or `video:`
      if (props.alt?.startsWith('audio:')) {
        return $(AudioPlayer, {src: props.src});
      }

      return $(ZoomableImage, {
        src: props.src,
        title: props.title ?? props.alt,
      });
    },
    list: (props: {children: any; depth: number; ordered: boolean}) =>
      $(
        View,
        {
          style: {
            paddingLeft: Dimensions.horizontalSpaceNormal * (props.depth + 1),
          },
        },
        props.children,
      ),

    listItem: (props: {children: any; index: number; ordered: boolean}) => {
      return $(
        Text,
        {...textProps, style: styles.listItemText},
        props.ordered
          ? $(Text, {style: styles.orderedBullet}, `${props.index + 1}. `)
          : $(Text, null, `\u2022 `),
        props.children,
      );
    },
  };

  return renderers;
}

export type Props = {
  text: string;
  onLayout?: ViewProps['onLayout'];
};

export default class Markdown extends PureComponent<Props> {
  public render() {
    const linkifySsbFeeds = linkifyRegex(Ref.feedIdRegex);
    const linkifySsbMsgs = linkifyRegex(Ref.msgIdRegex);
    const renderers = makeRenderers(this.props.onLayout);

    return $<any>(ReactMarkdown, {
      source: remark()
        .use(gemojiToEmoji)
        .use(linkifySsbFeeds)
        .use(linkifySsbMsgs)
        .use(imagesToSsbServeBlobs)
        .processSync(this.props.text).contents,
      astPlugins: [normalizeForReactNative()],
      allowedTypes: Object.keys(renderers),
      renderers,
    });
  }
}


fileFormatVersion: 2
guid: 583ff7026dac91849b7c7b2468ba456b
NativeFormatImporter:
  userData:
  assetBundleName:
  assetBundleVariant:


/**
 *
 * WARNING! This file was autogenerated by:
 *  _   _ _   _ __   __
 * | | | | | | |\ \ / /
 * | | | | |_| | \ V /
 * | | | |  _  | /   \
 * | |_| | | | |/ /^\ \
 *  \___/\_| |_/\/   \/
 *
 * This file was autogenerated by UnrealHxGenerator using UHT definitions.
 * It only includes UPROPERTYs and UFUNCTIONs. Do not modify it!
 * In order to add more definitions, create or edit a type with the same name/package, but with an `_Extra` suffix
**/
package unreal.moviescenetracks;

/**
  Handles manipulation of audio.
**/
@:umodule("MovieSceneTracks")
@:glueCppIncludes("Tracks/MovieSceneAudioTrack.h")
@:uextern @:uclass extern class UMovieSceneAudioTrack extends unreal.moviescene.UMovieSceneNameableTrack {

}


const express = require('express');
const request = require('request-promise')
const path = require('path')
const dotenv = require('dotenv')
const app = express();

const config = dotenv.config({ path: path.resolve(process.cwd(), "config", "config.env") })
const backendServiceEndpoint = `http://backend/hello-backend`

app.get('/hello-frontend', (req, res) => res.send(`Config says: ${config.parsed.MESSAGE}`));

app.get('/call-backend', (req, res) => {
  // Query the backend and return the response
  request.get(backendServiceEndpoint)
    .then(message => {
      message = `Backend says: '${message}'`
      res.json({
        message,
      })
    })
    .catch(err => {
      res.statusCode = 500
      res.json({
        error: err,
        message: "Unable to reach service at " + backendServiceEndpoint,
      })
    });
});

module.exports = { app }