/// <reference types="jquery"/>

interface JsObserve<T> {
	cdId: string;
	bnd: any;
}

interface JsObserveEventArgs<T> {
	change: string;
	path: string;
	value: T;
	oldValue: T;
	remove: boolean;
}

interface JsObserveEven<T> {
	currentTarget: T;
}

interface JsObservable<T> {

	observeAll<U>(handler: (ev: JsObserveEven<U>, eventArgs: JsObserveEventArgs<U>) => void): void;
	unobserveAll<U>(handler: (ev: JsObserveEven<U>, eventArgs: JsObserveEventArgs<U>) => void): void;

	setProperty<U>(path: string, value: U): void;
	setProperty<U>(path: string, path2: string, value: U): void;
	removeProperty(path: string): void;

	refresh<T>(items: T): void;

	remove<U>(data: U): void;
	remove<U>(index: Number, to: Number): void;
	insert<U>(value: U): void;
	insert<U>(index: number, value: U): void;
	insert<U>(index: number, value: Array<U>): void;
	move(oldIndex?: number, newIndex?: number, numToMove?: number): void;
	data(): T;
}

interface JQueryStatic {
	observable<T>(obj: T): JsObservable<T>;
	observable<T>(obj: T, path: string, handler: (ev: any, eventArgs: any) => any): JsObservable<T>;

	observe<T>(myObjectOrArray: T, handler: (ev: JQueryEventObject, eventArgs: JsObserveEventArgs<T>) => void): JsObserve<T>;
	observe<T>(myObjectOrArray: T, path: string, handler: (ev: JQueryEventObject, eventArgs: JsObserveEventArgs<T>) => void): JsObserve<T>;
	observe<T>(myObjectOrArray: T, path: string, path1: string, handler: (ev: JQueryEventObject, eventArgs: JsObserveEventArgs<T>) => void): JsObserve<T>;
	observe<T>(myObjectOrArray: T, path: string, path1: string, path2: string, handler: (ev: JQueryEventObject, eventArgs: JsObserveEventArgs<T>) => void): JsObserve<T>;

	unobserve<T>(myObjectOrArray: T, handler: (ev: JQueryEventObject, eventArgs: JsObserveEventArgs<T>) => void): JsObserve<T>;
	unobserve<T>(myObjectOrArray: T, path: string, handler: (ev: JQueryEventObject, eventArgs: JsObserveEventArgs<T>) => void): JsObserve<T>;
	unobserve<T>(myObjectOrArray: T, path: string, path1: string, handler: (ev: JQueryEventObject, eventArgs: JsObserveEventArgs<T>) => void): JsObserve<T>;
	unobserve<T>(myObjectOrArray: T, path: string, path1: string, path2: string, handler: (ev: JQueryEventObject, eventArgs: JsObserveEventArgs<T>) => void): JsObserve<T>;
}