livescores.js 3.74 KB
import jsonpatch from 'fast-json-patch/src/json-patch';

angular.module('footyroom')

.factory('livescores', ['$filter', '$rootScope', function ($filter, $rootScope) {
    var socket;

    var dayReportCb;
    var matchReportCb;
    var updateMatchCb;
    var updateDayCb;

    var subscribedMatchId;
    var subscribedMatch;
    var subscribedDay;
    var timezone;

    var dayReportDataVersion = 0;
    var matchReportDataVersion = 0;

    var subscribedDayDate;

    return {
        connect: connect,
        subMatch: subMatch,
        subDay: subDay,
    };

    // //////////

    function connect() {
        if (!socket) {
            socket = io(window.SITEURL, { path: '/livescores/socket.io/ws' });

            socket.on('full-data', onFullData);
            socket.on('match-report', onMatchReport);
            socket.on('update', onUpdate);
        }

        return socket;
    }

    function subMatch(matchId, reportCb, updateCb) {
        matchReportCb = reportCb;
        updateMatchCb = updateCb;
        subscribedMatchId = matchId;

        socket.emit('subscribe-match', { matchId: matchId });
    }

    function subDay(date, tz, reportCb, updateCb) {
        dayReportCb = reportCb;
        updateDayCb = updateCb;
        subscribedDayDate = date;
        timezone = tz;
        socket.emit('subscribe-day', { date: $filter('date')(date, 'yyyy-MM-dd'), timezone });
    }

    function preprocessMatches(matches) {
        _(matches).each(function (match) {
            if (match.incidents === undefined) {
                match.incidents = [];
            }

            if (match.lineup === undefined) {
                match.lineup = [];
            }
        });
    }

    function onFullData(data) {
        subscribedDay = data;

        dayReportDataVersion = data.version;

        preprocessMatches(subscribedDay.matchesById);

        dayReportCb(subscribedDay);

        $rootScope.$apply();
    }

    function onMatchReport(matchReport) {

        if (subscribedMatchId !== matchReport.match.matchId) {
            return;
        }

        subscribedMatch = matchReport.match;
        matchReportDataVersion = matchReport.version;

        matchReportCb && matchReportCb(subscribedMatch);

        $rootScope.$broadcast('formation-update');

        $rootScope.$apply();
    }

    function onUpdate(data) {
        if (data.matches) {
            onDayUpdate(data);
        } else if (subscribedMatch) {
            onMatchUpdate(data);
        }
    }

    function onDayUpdate(data) {
        if (data.version !== dayReportDataVersion + 1) {
            // Resubscribe to get full data
            socket.emit('subscribe-day', {
                date: $filter('date')(subscribedDayDate, 'yyyy-MM-dd'),
                timezone,
            });
        } else {
            dayReportDataVersion++; // Increment current data version
        }

        var oldMatchesLength = subscribedDay.matchesById.length;

        jsonpatch.apply(subscribedDay.matchesById, data.matches);

        if (subscribedDay.matchesById.length != oldMatchesLength) {
            preprocessMatches(subscribedDay.matchesById);
        }

        updateDayCb && updateDayCb(subscribedDay, data);

        $rootScope.$apply();
    }

    function onMatchUpdate(data) {
        if (data.version !== 'undefined' && data.version !== matchReportDataVersion + 1) {
            // Emit subscribe match event again to get full match report data again
            socket.emit('subscribe-match', { matchId: subscribedMatch.matchId });
        } else {
            matchReportDataVersion++;
        }

        jsonpatch.apply(subscribedMatch, data.patches);

        updateMatchCb && updateMatchCb(subscribedMatch, data.patches);

        $rootScope.$broadcast('formation-update');

        $rootScope.$apply();
    }
}]);