import {Inject, Injectable, NgZone, provide, OpaqueToken, Provider} from 'angular2/core';
import {Observable} from 'rxjs/Observable';
import {ConnectableObservable} from 'rxjs/observable/ConnectableObservable';
import Release = PDK.Release;
import {PlayerController} from './PDKControllerProvider';
import {Subject} from 'rxjs/Subject';
import {PDK_ACTIONS, ONPLAYERLOADED, ONMEDIAPLAYING} from './pdkActions';
const THROTTLE_ACTIONS = [ONMEDIAPLAYING, ONPLAYERLOADED];
@Injectable()
export class PDKPlayerObserver<Action> extends Subject<Action> {
/**
* @description Map over the PDK_ACTIONS event name and creates observables of the event listeners on the player
* emitting events of the same name without the prefix, then merges all emitted events into one observable.
* @param {NgZone} zone This is the angular change detection container. Since the PDK is a third party the Zone
* does not care about those events. So we need to tell Angular that stuff is happening. This is the equiilent of
* the much maligned $scope.apply in angular one.
* @param {PlayerController} _playerController This is the $pdk.controller present in the global context. We
* Angularized it so we didnt have to have any nasty lint globals.
* @returns {Observable<T>}
*/
constructor(@Inject(NgZone)
private zone,
@Inject(PlayerController)
private _playerController) {
/**
* Since we are extending the Subject we need to call the super class setup.
*/
super();
/**
* Map over the PDK_ACTION keys, get the name of the event and listen to it.
* Create a list of observables which correspond to each Event we listen to.
*/
let eventList = Object.keys(PDK_ACTIONS).map((constantName: string) => {
let eventName = PDK_ACTIONS[constantName];
/**
* @description Next an Observable when the listener fires.
* @param handler
*/
let add = (handler) => {
/**
* Using the pdk controller add the event listener.
*/
this._playerController.addEventListener(eventName, (event) => {
/**
* Tell angular about the change happening in the application.
*/
this.zone.run(() => {
/**
* Since this is a Subject we can next over it, adding an Action to the event stream at the time of the PDK
* event.
*/
handler({type: eventName, payload: event.data});
});
});
};
/**
* @description Shutdown the observable when the listener is removed.
* @param handler
*/
let remove = (handler) => {
this._playerController.removeEventListener(eventName, (event) => {
});
};
/**
* Create the Observable from above events.
* @type {FromEventPatternObservable<T, {}>}
*/
let observable: Observable<Action> = Observable.fromEventPattern(add, remove);
/**
* Some actions need to a "Whoa Cowboy" of 1 second
*/
if (THROTTLE_ACTIONS.indexOf(eventName) !== -1) {
/**
* Throttle the action
*/
observable = observable.throttleTime(1000);
}
return observable;
});
return this.merge(...eventList);
}
}