/// <reference path="./sigApi.PropertyObject.d.ts" />

declare namespace SigApi {
    interface ViewModel {
        /**
         * Returns the instanceId of the vm
         * 
         * @returns {string} The instanceId of the ViewModel
         */
        getInstanceId(): string
        /**
         * Returns the control id of the vm
         * 
         * @returns {string} The control id of the ViewModel
         */
        getControlId(): string
        /**
         * Returns the name of the vm
         * 
         * @returns {string} The name of the ViewModel 
         */
        getName(): string
        /**
         * Returns the DOM Reference of the Vm
         * 
         * @returns {HTMLElement|null} The Reference to the Object in the DOM Tree. (If it is null, the object has not been rendered yet)
         */
        getDomRef(): HTMLElement | null
        /**
         * Returns the isActive flag of the Vm
         * @returns {boolean}
         */
        isActive(): boolean
        /**
         * Registers the beforeSetActive callback or removes the callback by setting `null`. Only one callback can be registered at a time.
         * 
         * The callback is expected to return a boolean value:
         *  * true -> set the Vm to active
         *  * false -> do not set the Vm to active
         * @param {Function|null} callback signature: () => {boolean} doSetActive
         */
        registerBeforeSetActive(callback: (() => boolean) | null): void
        /**
         * Sets a Vm to active
         * * set children active
         * * set properties active
         * * set codeModules active
         */
        setActive(): void
        /**
         * Sets a Vm to inactive
         * * set children inactive
         * * set properties inactive
         * * set codeModules inactive
         */
        setInactive(): void
        /**
         * Shows (a hidden) control
         * * append domRef via `appendChildToParentDomRefCallback`
         * 
         * To keep public interface simple show can be called on a not (yet) rendered viewModel
         * and render will be called internally. 
         *
         * `appendChildToParentDomRefCallback` is expected to append the {HTMLElement}
         * to its parent domRef (`domRef.appendChild(element)`)
         * @param {Function} appendChildToParentDomRefCallback {Function} ({HTMLElement} element) not required if vm is already rendered
         */
        show(
            appendChildToParentDomRefCallback: (child: HTMLElement) => void
        ): void
        /**
         * Hides a ViewModel
         * * does not alter domRef structure
         * * does not alter viewModel parent-child structure
         * 
         * Depending on prerender/cacheDashboard flags and parameter preventDestroy the viewModel
         *  * properties might be destroyed
         *  * removeChildFromParentDomRefCallback is required to remove the domRef from its parent domRef
         *    `removeChildFromParentDomRefCallback` is expected to remove the {HTMLElement}
         *    from its parent domRef (`domRef.removeChild(element)`)
         * @param {Function} removeChildFromParentDomRefCallback {Function} ({HTMLElement} element)
         * @param {boolean} [preventDestroy=false] 
         */
        hide(
            removeChildFromParentDomRefCallback: (child: HTMLElement) => void,
            preventDestroy?: boolean
        ): void
        /**
         * Appends the viewModel to the parentVM domRef
         * * append domRef via `appendChildToParentDomRefCallback`
         * 
         * `appendChildToParentDomRefCallback` is expected to append the {HTMLElement}
         * to its parent domRef (`domRef.appendChild(element)`)
         * @param {Function} appendChildToParentDomRefCallback {Function} ({HTMLElement} element)
         * @param {number|number[]} [staticOv] 
         * @param {boolean} [hidden=false] 
         */
        render(
            appendChildToParentDomRefCallback: (child: HTMLElement) => void,
            staticOv?: number | Array<number>,
            hidden?: boolean
        ): void
        /**
         * @returns {object} { {string} instanceId, {string} parentId, {string} type }
         */
        getContext(): { instanceId: string, parentId?: string, type: 'dashboard' | 'window' }
        /**
         * @param {object} context { {string} instanceId, {string} parentId, {string} type }
         */
        setContext(context: { instanceId: string, parentId?: string, type: 'dashboard' | 'window' }): void
        /**
         * Destroys
         *  * viewModel instance
         *  * viewModel properties
         *  * viewModel children
         * 
         * depending on parameters.
         * 
         * In the case `destroyVmInstance: true`
         *  * removeChildFromParentDomRefCallback is required to remove the domRef from its parent domRef
         *    `removeChildFromParentDomRefCallback` is expected to remove the {HTMLElement}
         *    from its parent domRef (`domRef.removeChild(element)`)
         *  * the child viewModel is removed from its parent viewModel
         * @param {Function} removeChildFromParentDomRefCallback {Function} ({HTMLElement} element)
         * @param {boolean} [destroyVmInstance = false]
         * @param {boolean} [destroyPropertyInstances = false]
         * @param {boolean} [destroyVmChildInstances = false]
         */
        destroy(
            removeChildFromParentDomRefCallback: (child: HTMLElement) => void,
            destroyVmInstance?: boolean,
            destroyPropertyInstances?: boolean,
            destroyVmChildInstances?: boolean
        ): void
        /**
         * Returns the set slot for a VM. This is used to identify to which CC Property a VM belongs
         * 
         * @returns {string|undefined} the name of the slot, or undefined if the VM is not a CC 
         */
        getSlot(): string | undefined
        /**
         * Adds a child to parent ViewModel
         * 
         * The child needs to be created with `sigApi.vm.newViewModel`
         * 
         * The child is managed by the parent. One child must not be added to multiple parent viewModels.
         * @param {ViewModel} child 
         */
        addChild(child: ViewModel): void
        /**
         * Removes a child form a parent ViewModel
         * 
         * The child needs to be created with sigApi.vm.newViewModel
         * 
         * `removeChild` can be used to move a child from one parent to another efficiently, else `hide` or `destroy` should be preferred.
         * 
         * `removeChild` does not remove the viewModel domRef from parent viewModel domRef.
         * 
         * A removed child needs to be destroyed.
         * 
         * @param {ViewModel} child 
         */
        removeChild(child: ViewModel): void
        /**
         * Returns all Children of the current ViewModel
         * 
         * @returns {ViewModel[]} All children of the Vm
         */
        getChildren(): ViewModel[]
        /**
         * Finds a child of the current ViewModel by its instanceId.
         * 
         * @param {string} instanceId 
         * 
         * @returns {ViewModel|null} The child with the corresponding instanceId, or null if nothing was found
         */
        getChildByInstanceId(instanceId: string): ViewModel | null
        /**
         * Finds a child of the current ViewModel by its name. If a active CompositeControl is found,
         * the element is searched in the childlist of that CompositeControl
         * 
         * @param {string} name The name of the searched child
         * 
         * @returns {ViewModel|null} The child with the corresponding name, or null if nothing was found
         */
        getChildByName(name: string): ViewModel | null
        /**
         * Returns the blueprint of a property
         * 
         * @param {string} name The name of the searched child
         * @returns {undefined|PropertyObject} 
         */
        getPropertyObjByName(name: string): PropertyObject | undefined
        /**
         * Returns the Parent-VM
         * 
         * @returns {ViewModel|null} The parent ViewModel of the current ViewModel
         */
        getParent(): ViewModel | null
        /**
         * Overloads the ViewModel with the given Parameter
         * 
         * @param {number|string} dpId The datapoint id, or the name (inc. station eg. 0:Data00.Server21) of the datapoint with witch the overload should be made
         * @param {number} [selectionGroup=null] The number of the selection group which should be overloaded (null or undefined for any)
         * @param {number|string} [targetDp=null] The id or the name of the target datapoint which should be overloaded (null or undefined for any)
         */
        overload(
            dpId: number | string,
            selectionGroup?: number,
            targetDp?: number | string
        ): void
        /**
         * Resets previous overloads
         */
        resetOverload(): void
        /**
         * Adds a code module object to the view Model
         * 
         * @param {string} moduleName Name at which the code module should be added.
         * @param {object} moduleObj Code module that should be added as javaScript Object.
         */
        addCodeModule(moduleName: string, moduleObj: object): void
        /**
         * Returns a code module object previously added to the view model
         * 
         * @param {string} [moduleName=undefined] Name of the code module added by a call to addCodeModule. Pass undefined if you want to get the codeModule registered to this viewModel.
         * 
         * @returns {object|null} The code module registered to given name or null if not module was found
         */
        getCodeModule(moduleName?: string): any
        /**
         * This function will dynamically append a new composite control property to this viewmodel.
         * After success, you may use "sigApi.properties.getProperty(this.getInstanceId(), slotName)" to obtain the property or
         * use "sigApi.vm.removeCC(this, slotName) to remove the property.
         * For static overload (overload at creation) use the staticOvDpId parameter (minimal performance impact).
         * For dynamic overload (overload after creation) use the "Property.overload()" api after obtaining the property (higher performance impact).
         * 
         * @param {string} ccName The name of the composite control which should be rendered
         * @param {string} slotName The name of the slot in which the composite control should be rendered (also used as name for the composite control property)
         * @param {number|string} [staticOvDpId=null] The id or the name of the datapoint for the static overload, or null if no static overload should be done
         * @param {boolean} [deferedUse=false] If set to true the new CC is not setActive automatically and has style class sig-element-no-render (display: none) applied
         * @param {DocumentFragment} [documentFragment] A documentFragment to append to instead of parentVM domRef
         * @returns {boolean} true if the composite control property was added successfully and false if it was not
         */
        appendNewCC(
            ccName: string,
            slotName: string,
            staticOvDpId?: number | string,
            deferedUse?: boolean,
            documentFragment?: DocumentFragment
        ): boolean
        /**
         * This function will dynamically append a new composite control scheme property to this viewmodel.
         * After success, you may use "sigApi.properties.getProperty(this.getInstanceId(), slotName)" to obtain the property or
         * use "this.removeCC(slotName)" or "sigApi.vm.removeCC(this, slotName) to remove the property.
         * For static overload (overload at creation) use the staticOvDpId parameter (minimal performance impact).
         * For dynamic overload (overload after creation) use the "Property.overload()" api after obtaining the property (higher performance impact).
         * Be aware that a composite control scheme property is asynchronous and can change its state at all times due to datapoint evaluation/change.
         * Consider obtaining the property and use "Property.addObserver()" api to get notified on changes.
         * 
         * @param {string} schemeName The name of the composite control scheme which should be added
         * @param {string|number} schemeInputDpId The id or the name of the input datapoint for the composite control scheme (if a number with a 'c' at the end is given, that number is used as constant input e.g. '12c')
         * @param {string} slotName The name of the slot in which the composite control should be rendered (also used as name for the composite control scheme property)
         * @param {string} [defaultCCName=undefined] The name of the composite control which should be used if no scheme entry is selected. If null/undefined is given, then there will be no default
         * @param {number|string} [staticOvDpId=null] The id or the name of the datapoint for the static overload, or null if no static overload should be done
         * @returns {boolean} true if the composite control scheme property was added successfully and false if it was not
         */
        appendNewCCScheme(
            schemeName: string,
            schemeInputDpId: number | string,
            slotName: string,
            defaultCCName?: string,
            staticOvDpId?: number | string
        ): boolean
        /**
         * This function will dynamically remove the given composite control (scheme) property from this viewmodel
         * 
         * @param {string} slotName The name of the slot where the composite control is rendered (also used as name for the composite control (scheme) property)
         * @returns {boolean} true if the composite control (scheme) property was removed successfully or false if it was not
         */
        removeCC(slotName: string): boolean
    }
}
