define('application/managers/epg', [
'product-layer/epg/manager',
'application/managers/api',
'rofl/lib/utils',
'rofl/lib/promise',
'antie/runtimecontext'
], function (
AbstractEpgManager,
ApiManager,
Utils,
Promise,
RuntimeContext
) {
'use strict';
var api,
DATA_CHUNK_TIME_SPAN = 24 * 60 * 60,
instance,
app,
EpgManager;
EpgManager = AbstractEpgManager.extend({
/**
* Initialises the EPG manager.
*/
init: function init () {
init.base.call(this);
api = ApiManager.getKPNAPI();
app = RuntimeContext.getCurrentApplication();
this.setDataChunkTimeSpan(24 * 60 * 60);
},
/**
* Loads the data for the given channel ids and time.
*
* @param {Array} channelIds - The channel ids.
* @param {number} time - The time in seconds.
* @returns {Promise} - Promise resolving with epg data.
*/
load: function (channelIds, time) {
return api.read('epg', {
params: {
channels: channelIds,
startTime: time * 1000,
endTime: (time + this.getDataChunkTimeSpan()) * 1000
}
});
},
/**
* Initiator of the EPG data loading.
*
* @param {Array} channelIds - Channel ID's to fetch.
* @param {number} time - Regulated time for fetching the correct time slot.
* @returns {Promise} The load promise.
*/
loadData: function (channelIds, time) {
var timeSlot = this._regulateTimeSlot(time),
self = this,
slot = {};
return this.load(channelIds, timeSlot).then(function (epgData) {
if (epgData) {
slot.timeSlot = timeSlot;
slot.previousSlot = timeSlot - DATA_CHUNK_TIME_SPAN;
slot.nextSlot = timeSlot + DATA_CHUNK_TIME_SPAN;
slot.compared = false;
// Make sure the time slot exists
if (!self._slots[timeSlot]) {
self._slots[timeSlot] = {};
}
if (Utils.keys(epgData).length) {
Utils.extend(self._slots[timeSlot], epgData);
}
return Promise.resolve(epgData);
}
return Promise.resolve();
});
},
/**
* Get the current and prev EPG item for a channel ID.
*
* @param {String|Number|Array} channelIds - Channel ID's to load the data for.
* @returns {Promise} EPG data promise.
*/
getNowPrev: function (channelIds) {
var self = this,
currentTime = Math.round((app.getDate()).getTime() / 1000),
channels;
if (Utils.isArray(channelIds)) {
channels = channelIds;
} else if (Utils.isString(channelIds) || Utils.isNumber(channelIds)) {
channels = [channelIds];
}
return this.getItem(channels, currentTime).then(function (items) {
var fillMissingPrevs = Utils.bind(self._fillMissingPrevs, self),
fillMissingPrevsInCurrentTime = Utils.bind(self._fillMissingPrevsInCurrentTime, self),
prevTime = currentTime - DATA_CHUNK_TIME_SPAN,
prevTimeSlot = prevTime - (prevTime % DATA_CHUNK_TIME_SPAN),
currentTimeSlot = currentTime - (currentTime % DATA_CHUNK_TIME_SPAN);
if (currentTime > currentTimeSlot) {
return fillMissingPrevsInCurrentTime(currentTimeSlot, items).then(function (filledItems) {
var epgItems = {};
Utils.each(filledItems, function (value, key) {
epgItems[key] = {
now: value.item,
prev: value.prev
};
});
return fillMissingPrevs(prevTimeSlot, items)
.then(function (prevItems) {
Utils.each(prevItems, function (value, key) {
epgItems[key] = {
now: value.item,
prev: value.prev
};
});
return Promise.resolve(epgItems);
});
});
}
return fillMissingPrevs(prevTimeSlot, items).then(function (filledItems) {
var epgItems = {};
Utils.each(filledItems, function (value, key) {
epgItems[key] = {
now: value.item,
prev: value.prev
};
});
return Promise.resolve(epgItems);
});
});
},
/**
* Tries to fill in the blanks, retrieved from the prev time span.
*
* @param {number} time - The time to check for.
* @param {Object} items - The original item to check against.
* @returns {Promise} Load promise.
*/
_fillMissingPrevs: function (time, items) {
var missingPrevs = [],
self = this;
Utils.each(items, function (value, key) {
if (!value.prev) {
missingPrevs.push(key);
}
});
return this._loadMissingData(missingPrevs, time).then(function () {
var i = 0,
max = missingPrevs.length,
channelId,
channelSlot,
item,
j,
itemAmount;
for (; i < max; i++) {
channelId = missingPrevs[i];
channelSlot = self._getChannelSlot(channelId, time);
for (j = 0, itemAmount = channelSlot.length; j < itemAmount; j++) {
item = channelSlot[itemAmount - 1];
items[channelId].prev = item || null;
}
}
return Promise.resolve(items);
});
},
/**
* Tries to fill in the blanks, retrieved from the prev time span.
*
* @param {number} time - The time to check for.
* @param {Object} items - The original item to check against.
* @returns {Promise} Load promise.
*/
_fillMissingPrevsInCurrentTime: function (time, items) {
var missingPrevs = [],
self = this;
Utils.each(items, function (value, key) {
if (!value.prev) {
missingPrevs.push(key);
}
});
return this._loadMissingData(missingPrevs, time).then(function () {
var i = 0,
max = missingPrevs.length,
channelId,
channelSlot,
currentItem,
item,
j,
itemAmount;
for (; i < max; i++) {
channelId = missingPrevs[i];
channelSlot = self._getChannelSlot(channelId, time);
currentItem = items[channelId].item;
for (j = 0, itemAmount = channelSlot.length; j < itemAmount; j++) {
if (channelSlot[j] === currentItem) {
item = channelSlot[j - 1];
items[channelId].prev = item || null;
}
}
}
return Promise.resolve(items);
});
}
});
return {
/**
* Returns an instance of the epg manager.
*
* @returns {Object} - The epg manager instance.
*/
getInstance: function () {
if (!instance) {
instance = new EpgManager();
}
return instance;
}
};
});