player.ts 2.92 KB
import { EventEmitter } from 'events';
import {ProgramRepository} from './program-repository';
import {ProgramManager} from './program-manager';
import {Util} from './util';

const STATE_START = "start";
const STATE_STOP  = "stop";

export class Player extends EventEmitter {

    protected _programRepository:ProgramRepository;
    protected _programManager:ProgramManager;
    protected _minutesReplication:number = 5;
    protected _replicationRetry:number = 10000;

    protected _currentProgramItemId:string = '';
    protected _currentReplicationCounter:number = 0;
    protected _state = STATE_STOP;

    set state(st:string) {
        this._state = st;
    }

    set programManager(pm:ProgramManager) {
        this._programManager = pm;
    }

    get programManager() : ProgramManager {
        return this._programManager;
    }

    set programRepository(pr:ProgramRepository) {
        this._programRepository = pr;
    }

    get programRepository() : ProgramRepository {
        return this._programRepository;
    }

    set minutesReplication(mr:number) {
        this._minutesReplication = mr;
    }

    get minutesReplication() : number {
        return this._minutesReplication;
    }

    set replicationRetry(rr:number) {
        this._replicationRetry = rr;
    }

    get replicationRetry() : number {
        return this._replicationRetry;
    }

    triggerReplication() : Promise<void> {
        return this.programRepository.replicate()
            .then(() => { 
                this._currentReplicationCounter = 0;
                this.trigger(this.triggerProgramItemId, Util.calculateNextMinute());
            })
            .catch(() => {
                this.trigger(this.triggerReplication, this.replicationRetry);
            });
    }

    triggerProgramItemId() {
        this.programManager.getCurrentProgramItemId()
            .then(programItemId => {
                this._currentReplicationCounter++;

                // if there is a new program item id trigger play
                // else (1) calculate next potential program change point
                // or (2) trigger replication

                if (programItemId != this._currentProgramItemId) {
                    this._currentProgramItemId = programItemId;
                    this.emit('play', programItemId);
                } else if (this._currentReplicationCounter >= this._minutesReplication) {
                    this.triggerReplication();
                } else {
                    this.trigger(this.triggerProgramItemId, Util.calculateNextMinute());
                }
            });
    }

    trigger(func:Function, milliseconds:number) {
        if (this._state === STATE_START) { 
            setTimeout(() => { func(); }, milliseconds);
        }        
    }

    start() {
        if (this._state === STATE_STOP) {
            this.triggerReplication();
            this._state = STATE_START;
        }
    }

    stop() {
        this._state = STATE_STOP;
    }

}