define([], function () { 'use strict'; function getLibarytemTypes(serverId) { let types = NativeItemRepository.getLibraryItemTypes(serverId); return Promise.resolve(JSON.parse(types)); } function getLibraryItemsByIds(serverId, ids) { let items = NativeItemRepository.getLibraryItemsByIds(serverId, ids); return Promise.resolve(JSON.parse(items)); } function getLibraryItemPathsByIds(serverId, ids) { return getLibraryItemsByIds(serverId, ids).then(function (items) { var paths = items.reduce(function (result, item) { if (item) { var id_path = { ItemId: item.ItemId, LocalPath: '' }; if (item.LocalPath) { id_path.LocalPath = item.LocalPath; } else if (item.Item && item.Item.MediaSources && item.Item.MediaSources.length) { var mediaSource = item.Item.MediaSources[0]; id_path.LocalPath = mediaSource.StreamUrl || mediaSource.Path; } result.push(id_path); } return result; }, []); return Promise.resolve(paths); }).catch(function (error) { return Promise.resolve([]); }); } function getLibraryItemsBySyncStatus(serverId, syncStati) { throw new Error('getLibraryItemsBySyncStatus not implemented'); } function getLibraryItemsByType(serverId, itemTypes, options) { let items = NativeItemRepository.getLibraryItemsByType(serverId, itemTypes); return Promise.resolve(JSON.parse(items)); } function getAllLibraryItems(serverId) { return Promise.resolve(JSON.parse(NativeItemRepository.getAllLibraryItems(serverId))); } function getLibraryItem(serverId, itemId) { var json = NativeItemRepository.getLibraryItem(serverId, itemId); return json ? Promise.resolve(JSON.parse(json)) : Promise.resolve(null); } function addLibraryItem(serverId, key, val) { throw new Error('addLibraryItem not implemented'); } function updateLibraryItem(serverId, key, val) { NativeItemRepository.updateLibraryItem(JSON.stringify(val)); return Promise.resolve(); } function deleteLibraryItem(serverId, itemId) { NativeItemRepository.deleteLibraryItem(serverId, itemId); return Promise.resolve(); } function clearLibrary(serverId) { throw new Error('clearLibrary not implemented'); } function getLibraryItems(serverId, options) { var searchParentId = options.ParentId; searchParentId = normalizeId(searchParentId); var seasonId = normalizeId(options.SeasonId || options.seasonId); var seriesId = normalizeId(options.SeriesId || options.seriesId); var albumIds = normalizeIdList(options.AlbumIds || options.albumIds); var includeItemTypes = options.IncludeItemTypes ? options.IncludeItemTypes.split(',') : []; var filters = options.Filters ? options.Filters.split(',') : []; var mediaTypes = options.MediaTypes ? options.MediaTypes.split(',') : []; if (updateFiltersForTopLevelView(searchParentId, mediaTypes, includeItemTypes, options)) { searchParentId = null; } var getPromise = Promise.resolve(); if (searchParentId) { getPromise = getLibraryItem(serverId, searchParentId).then(function (item) { if (item && item.Item) { if (item.Item.Type === 'MusicAlbum') { options.Recursive = true; includeItemTypes.push('Audio'); if (!albumIds.includes(searchParentId)) { albumIds.push(searchParentId); searchParentId = null; } options.SortBy = options.SortBy || "ParentIndexNumber,IndexNumber,SortName"; } else if (item.Item.Type === "Series") { seriesId = searchParentId; searchParentId = null; options.SortBy = options.SortBy || options.Recursive ? "ParentIndexNumber,IndexNumber" : "IndexNumber"; } else if (item.Item.Type === "Season") { seriesId = searchParentId; searchParentId = null; options.SortBy = options.SortBy || "ParentIndexNumber,IndexNumber,SortName"; } } }); } if (includeItemTypes.length) { getPromise = getPromise.then(function () { var includeSet = Array.from(new Set(includeItemTypes)); includeItemTypes = []; return getLibraryItemsByType(serverId, includeSet); }); } else { getPromise = getPromise.then(function () { return getAllLibraryItems(serverId); }); } return getPromise.then(function (items) { var itemsMap = new Map(); var subtreeIdSet = new Set(); // create a map for quick access items.forEach(function (item) { item.Item.LocalChildren = []; itemsMap.set(item.Item.Id, item.Item); }); // add each item to its parent's LocalChildren collection if parent exists itemsMap.forEach(function (item) { if (item.ParentId && itemsMap.has(item.ParentId)) { var parentItem = itemsMap.get(item.ParentId); parentItem.LocalChildren.push(item); } }); // create a set containing all item ids that are descendants from searchParentId if (options.Recursive && searchParentId && itemsMap.has(searchParentId)) { var addSubtreeIds = function (recurseItem) { if (!subtreeIdSet.has(recurseItem.Id)) { subtreeIdSet.add(recurseItem.Id); } recurseItem.LocalChildren.forEach(function (childItem) { addSubtreeIds(childItem); }); }; var searchParentItem = itemsMap.get(searchParentId); addSubtreeIds(searchParentItem); } var resultItems = items.filter(function (item) { if (item.SyncStatus && item.SyncStatus !== 'synced') { return false; } if (mediaTypes.length) { if (mediaTypes.indexOf(item.Item.MediaType || '') === -1) { return false; } } if (seriesId && item.Item.SeriesId !== seriesId) { return false; } if (seasonId && item.Item.SeasonId !== seasonId) { return false; } if (albumIds.length && albumIds.indexOf(item.Item.AlbumId || '') === -1) { return false; } if (item.Item.IsFolder && filters.indexOf('IsNotFolder') !== -1) { return false; } else if (!item.Item.IsFolder && filters.indexOf('IsFolder') !== -1) { return false; } if (includeItemTypes.length) { if (includeItemTypes.indexOf(item.Item.Type || '') === -1) { return false; } } if (searchParentId) { if (options.Recursive) { return subtreeIdSet.has(item.Item.Id); } else { return item.Item.ParentId === searchParentId; } } return true; }).map(function (item2) { return item2.Item; }); resultItems = sortItems(resultItems, options); var totalRecordCount = resultItems.length; if (options.StartIndex) { resultItems = resultItems.slice(options.StartIndex); } if (options.Limit != null) { resultItems = resultItems.slice(0, options.Limit); } return Promise.resolve({ Items: resultItems, TotalRecordCount: totalRecordCount }); }); } function sortItems(items, query) { if (query.LocalSortBy && query.LocalSortBy.length !== 0) { // option LocalSortBy overrides SortBy option query.SortBy = query.LocalSortBy; } if (!query.SortBy || query.SortBy.length === 0) { return items; } if (query.SortBy === 'Random') { return shuffle(items); } var sortSpec = getSortSpec(query); items.sort(function (a, b) { for (var i = 0; i < sortSpec.length; i++) { var result = compareValues(a, b, sortSpec[i].Field, sortSpec[i].OrderDescending); if (result !== 0) { return result; } } return 0; }); return items; } function compareValues(a, b, field, orderDesc) { if (!a.hasOwnProperty(field) || !b.hasOwnProperty(field)) { // property doesn't exist on both objects return 0; } var valA = a[field]; var valB = b[field]; var result = 0; if (typeof valA === 'string' || typeof valB === 'string') { valA = valA || ''; valB = valB || ''; result = valA.toLowerCase().localeCompare(valB.toLowerCase()); } else { if (valA > valB) { result = 1; } else if (valA < valB) { result = -1; } } if (orderDesc) { result *= -1; } return result; } function shuffle(array) { var currentIndex = array.length, temporaryValue, randomIndex; // While there remain elements to shuffle... while (0 !== currentIndex) { // Pick a remaining element... randomIndex = Math.floor(Math.random() * currentIndex); currentIndex -= 1; // And swap it with the current element. temporaryValue = array[currentIndex]; array[currentIndex] = array[randomIndex]; array[randomIndex] = temporaryValue; } return array; } function getSortSpec(query) { var sortFields = (query.SortBy || '').split(','); var sortOrders = (query.SortOrder || '').split(','); var sortSpec = []; for (var i = 0; i < sortFields.length; i++) { var orderDesc = false; if (i < sortOrders.length && sortOrders[i].toLowerCase().indexOf('desc') !== -1) { orderDesc = true; } sortSpec.push({ Field: sortFields[i], OrderDescending: orderDesc }); } return sortSpec; } function updateFiltersForTopLevelView(parentId, mediaTypes, includeItemTypes, query) { switch (parentId) { case 'MusicView': if (query.Recursive) { includeItemTypes.push('Audio'); } else { includeItemTypes.push('MusicAlbum'); } return true; case 'PhotosView': if (query.Recursive) { includeItemTypes.push('Photo'); } else { includeItemTypes.push('PhotoAlbum'); } return true; case 'TVView': if (query.Recursive) { includeItemTypes.push('Episode'); } else { includeItemTypes.push('Series'); } return true; case 'VideosView': if (query.Recursive) { includeItemTypes.push('Video'); } else { includeItemTypes.push('Video'); } return true; case 'MoviesView': if (query.Recursive) { includeItemTypes.push('Movie'); } else { includeItemTypes.push('Movie'); } return true; case 'MusicVideosView': if (query.Recursive) { includeItemTypes.push('MusicVideo'); } else { includeItemTypes.push('MusicVideo'); } return true; case 'TrailersView': if (query.Recursive) { includeItemTypes.push('Trailer'); } else { includeItemTypes.push('Trailer'); } return true; } return false; } function normalizeId(id) { if (id) { id = stripStart(id, 'localview:'); id = stripStart(id, 'local:'); return id; } return null; } function normalizeIdList(val) { if (val) { return val.split(',').map(normalizeId); } return []; } function stripStart(str, find) { if (startsWith(str, find)) { return str.substr(find.length); } return str; } function startsWith(str, find) { if (str && find && str.length > find.length) { if (str.indexOf(find) === 0) { return true; } } return false; } return { getLibarytemTypes: getLibarytemTypes, getLibraryItemsByIds: getLibraryItemsByIds, getLibraryItemPathsByIds: getLibraryItemPathsByIds, getLibraryItemsBySyncStatus: getLibraryItemsBySyncStatus, getLibraryItemsByType: getLibraryItemsByType, getAllLibraryItems: getAllLibraryItems, getLibraryItem: getLibraryItem, getLibraryItems: getLibraryItems, addLibraryItem: addLibraryItem, updateLibraryItem: updateLibraryItem, deleteLibraryItem: deleteLibraryItem, clearLibrary: clearLibrary }; });