Source: managers/genre.js

define('application/managers/genre', [
    'antie/class',
    'rofl/lib/utils',
    'application/managers/search',
    'rofl/lib/promise',
    'antie/runtimecontext'
], function (
    Class,
    Utils,
    SearchManager,
    Promise,
    RuntimeContext
) {

    'use strict';

    var GENRES = {
            Amusement: {
                name: 'Amusement',
                values: ['Amusement', 'Dans', 'Dating', 'Infotainment', 'Quiz', 'Reality', 'Spelshow', 'Talkshow']
            },
            Documentaire: {
                name: 'Documentaire',
                values: ['Documentaire', 'Biografie', 'Geschiedenis']
            },
            Film: {
                name: 'Film',
                values: ['Film', 'Films op TV', 'Filmhuis']
            },
            Humor: {
                name: 'Humor',
                values: ['Humor', 'Cabaret', 'Satire']
            },
            Informatief: {
                name: 'Informatief',
                values: ['Informatief', 'Consumenten', 'Dieren', 'Educatief', 'Interview en debat', 'Medisch', 'Natuur', 'Opvoeding', 'Reizen', 'Wetenschap', 'Wetenschap en Techniek', 'Kunst en cultuur', 'Religieus']
            },
            Kids: {
                name: 'Kids',
                values: ['Kinderen', 'Jeugd']
            },
            Lifestyle: {
                name: 'Lifestyle',
                values: ['Lifestyle', 'Auto', 'Fietsen', 'Gezondheid', 'Huis en Tuin', 'Klussen', 'Koken']
            },
            Misdaad: {
                name: 'Misdaad',
                values: ['Misdaad', 'Detective']
            },
            Muziek: {
                name: 'Muziek',
                values: ['Muziek', 'Musical']
            },
            'Nieuws en Actualiteiten': {
                name: 'Nieuws en Actualiteiten',
                values: ['Actualiteiten', 'Nieuws', 'Politiek']
            },
            'Series & Soaps': {
                name: 'Series & Soaps',
                values: ['Serie', 'Soap']
            },
            Sport: {
                name: 'Sport',
                values: ['Sport', 'Golf', 'Live Voetbal', 'Schaatsen', 'Tennis', 'Vechtsport', 'Voetbal', 'Wedstrijd']
            }
        },
        MOVIE_GENRES = {
            Actie: {
                name: 'Actie',
                values: ['Actie', 'Western', 'Sport']
            },
            Animatie: {
                name: 'Animatie',
                values: ['Animatie']
            },
            Avontuur: {
                name: 'Avontuur',
                values: ['Avontuur']
            },
            Biografie: {
                name: 'Biografie',
                values: ['Biografie']
            },
            Comedy: {
                name: 'Comedy',
                values: ['Cabaret', 'Humor', 'Satire', 'Amusement']
            },
            Documentaire: {
                name: 'Documentaire',
                values: ['Documentaire']
            },
            Drama: {
                name: 'Drama',
                values: ['Drama', 'Actualiteiten']
            },
            Familie: {
                name: 'Familie',
                values: ['Kinderen', 'Jeugd', 'Familie', 'Animatie', 'Educatief']
            },
            Fantasy: {
                name: 'Fantasy',
                values: ['Fantasie']
            },
            Filmhuis: {
                name: 'Filmhuis',
                values: ['Filmhuis']
            },
            Historisch: {
                name: 'Historisch',
                values: ['Geschiedenis', 'Oorlog']
            },
            Horror: {
                name: 'Horror',
                values: ['Horror']
            },
            Misdaad: {
                name: 'Misdaad',
                values: ['Misdaad', 'Detective']
            },
            Muziek: {
                name: 'Muziek',
                values: ['Muziek', 'Musical', 'Dans']
            },
            Mystery: {
                name: 'Mystery',
                values: ['Mysterie']
            },
            Natuur: {
                name: 'Natuur',
                values: ['Natuur', 'Dieren']
            },
            'Nederlands gesproken': {
                name: 'Nederlands gesproken',
                values: ['Nederlands']
            },
            Romantiek: {
                name: 'Romantiek',
                values: ['Romantiek']
            },
            'Science fiction': {
                name: 'Science fiction',
                values: ['Science fiction']
            },
            Thriller: {
                name: 'Thriller',
                values: ['Thriller']
            }
        },
        GenreManager,
        searchManager = SearchManager.getInstance(),
        app = RuntimeContext.getCurrentApplication(),
        instance;

    GenreManager = Class.extend({

        /**
         * Initialises the genre manager.
         */
        init: function () {

            this._slots = {};
        },

        /**
         * Retrieve the data for the given genre key and date.
         *
         * @param {string} genreKey - The genre key to retrieve the data for.
         * @param {Date} date - The date to retrieve the data for.
         * @returns {Promise} - Promise resolving with the data for the given genre key and date.
         */
        getData: function (genreKey, date) {
            var dateTime,
                slot,
                endDate;

            date = this._formatTimeSlot(date);
            dateTime = date.getTime();
            endDate = new Date(dateTime + 24 * 60 * 60 * 1000);

            if (!this._slots[genreKey]) {
                this._slots[genreKey] = {};
            }

            slot = this._slots[genreKey][dateTime];

            if (!slot) {
                this._slots[genreKey][dateTime] = {};

                return this._loadMissingData(genreKey, dateTime, endDate.getTime())
                    .then(Utils.bind(function () {

                        return this._slots[genreKey][dateTime];
                    }, this));
            }

            return Promise.resolve(slot);
        },

        /**
         * Attempts to load and save the missing data.
         *
         * @param {string} genreKey - The genre key.
         * @param {number} date - The numeric start date.
         * @param {number} endDate - The numeric end date.
         * @returns {Promise} - Promise resolving when the data has been loaded and saved.
         * @private
         */
        _loadMissingData: function (genreKey, date, endDate) {
            var valueToLoad = GENRES[genreKey].values, // API does not support multiple genres, use single genre for now.
                self = this;

            return searchManager.searchByGenre(
                valueToLoad,
                date,
                endDate,
                false
            ).then(
                    function (results) {
                        self._saveResults(date, genreKey, results);
            });
        },

        /**
         * Saves the results in the slot.
         *
         * @param {number} date - The numeric date.
         * @param {string} genreKey - The genre key.
         * @param {Object} results - The results.
         * @private
         */
        _saveResults: function (date, genreKey, results) {
            this._slots[genreKey][date] = results;
        },

        /**
         * Formats the time slot.
         *
         * @param {Date} timeSlot - The time slot to format.
         * @returns {Date} - The formatted date.
         * @private
         */
        _formatTimeSlot: function (timeSlot) {
            if (!timeSlot) {
                timeSlot = app.getDate();
            }

            timeSlot.setHours(2);
            timeSlot.setMinutes(0);
            timeSlot.setSeconds(0);
            timeSlot.setMilliseconds(0);

            return timeSlot;
        }
    });

    return {

        getInstance: function () {
            if (!instance) {
                instance = new GenreManager();
            }

            return instance;
        },

        GENRES: GENRES,
        MOVIE_GENRES: MOVIE_GENRES
    };
});