define(['filerepository', 'itemrepository', 'userrepository', 'useractionrepository', 'transfermanager', 'cryptojs-md5'], function (filerepository, itemrepository, userrepository, useractionrepository, transfermanager) {
    'use strict';

    function getLocalItem(serverId, itemId) {
        var id = getLocalId(serverId, itemId);
        return itemrepository.get(id);
    }

    function getLocalItemById(id) {
        return itemrepository.get(id);
    }

    function getLocalId(serverId, itemId) {

        return CryptoJS.MD5(serverId + itemId).toString();
    }

    function saveOfflineUser(user) {
        return userrepository.set(user.Id, user);
    }

    function deleteOfflineUser(id) {
        return userrepository.remove(id);
    }

    function recordUserAction(action) {

        action.Id = createGuid();
        return useractionrepository.set(action.Id, action);
    }

    function getUserActions(serverId) {
        return useractionrepository.getByServerId(serverId);
    }

    function deleteUserAction(action) {
        return useractionrepository.remove(action.Id);
    }

    function deleteUserActions(actions) {
        var results = [];

        actions.forEach(function (action) {
            results.push(deleteUserAction(action));
        });

        return Promise.all(results);
    }

    function getServerItemIds(serverId) {
        return itemrepository.getServerItemIds(serverId);
    }

    function getServerItems(serverId) {

        return itemrepository.getServerIds(serverId).then(function (localIds) {

            var actions = localIds.map(function (id) {
                return getLocalItemById(id);
            });

            return Promise.all(actions).then(function (items) {

                return Promise.resolve(items);
            });
        });
    }

    function getViews(serverId, userId) {

        return itemrepository.getServerItemTypes(serverId, userId).then(function (types) {

            var list = [];
            var item;

            if (types.indexOf('audio') > -1) {

                item = {
                    Name: 'Music',
                    ServerId: serverId,
                    Id: 'localview:MusicView',
                    Type: 'MusicView',
                    CollectionType: 'Music',
                    IsFolder: true
                };

                list.push(item);
            }

            if (types.indexOf('photo') > -1) {

                item = {
                    Name: 'Photos',
                    ServerId: serverId,
                    Id: 'localview:PhotosView',
                    Type: 'PhotosView',
                    CollectionType: 'Photos',
                    IsFolder: true
                };

                list.push(item);
            }

            if (types.indexOf('episode') > -1) {

                item = {
                    Name: 'TV',
                    ServerId: serverId,
                    Id: 'localview:TVView',
                    Type: 'TVView',
                    CollectionType: 'TvShows',
                    IsFolder: true
                };

                list.push(item);
            }

            if (types.indexOf('video') > -1 ||
                types.indexOf('movie') > -1 ||
                types.indexOf('musicvideo') > -1) {

                item = {
                    Name: 'Videos',
                    ServerId: serverId,
                    Id: 'localview:VideosView',
                    Type: 'VideosView',
                    CollectionType: 'HomeVideos',
                    IsFolder: true
                };

                list.push(item);
            }

            return Promise.resolve(list);
        });
    }

    function getViewItems(serverId, userId, parentId) {

        return getServerItems(serverId).then(function (items) {

            var resultItems = items.filter(function (item) {

                var type = (item.Item.Type || '').toLowerCase();

                switch (parentId) {
                    case 'localview:MusicView':
                        return type === 'audio';
                    case 'localview:PhotosView':
                        return type === 'photo';
                    case 'localview:TVView':
                        return type === 'episode';
                    case 'localview:VideosView':
                        return type === 'movie' || type === 'video' || type === 'musicvideo';
                    default:
                        return false;
                }
            }).map(function (item2) {
                return item2.Item;
            });

            return Promise.resolve(resultItems);
        });
    }


    function removeLocalItem(localItem) {

        return itemrepository.get(localItem.Id).then(function (item) {
            return filerepository.deleteFile(item.LocalPath).then(function () {

                var p = Promise.resolve(true);

                if (item.AdditionalFiles) {
                    item.AdditionalFiles.forEach(function (file) {
                        p = p.then(function () {
                            return filerepository.deleteFile(file.Path);
                        });
                    });
                }

                return p.then(function (file) {
                    return itemrepository.remove(localItem.Id);
                });

            }, function (error) {

                var p = Promise.resolve(true);

                if (item.AdditionalFiles) {
                    item.AdditionalFiles.forEach(function (file) {
                        p = p.then(function (item) {
                            return filerepository.deleteFile(file.Path);
                        });
                    });
                }

                return p.then(function (file) {
                    return itemrepository.remove(localItem.Id);
                });
            });
        });
    }

    function addOrUpdateLocalItem(localItem) {
        return itemrepository.set(localItem.Id, localItem);
    }

    function createLocalItem(libraryItem, serverInfo, jobItem) {

        var path = getDirectoryPath(libraryItem, serverInfo);
        var localFolder = filerepository.getFullLocalPath(path);

        path.push(getLocalFileName(libraryItem, jobItem.OriginalFileName));

        var localPath = filerepository.getFullLocalPath(path);

        for (var i = 0; i < libraryItem.MediaSources.length; i++) {
            var mediaSource = libraryItem.MediaSources[i];
            mediaSource.Path = localPath;
            mediaSource.Protocol = 'File';
        }

        var item = {

            Item: libraryItem,
            ItemId: libraryItem.Id,
            ServerId: serverInfo.Id,
            LocalPath: localPath,
            LocalFolder: localFolder,
            AdditionalFiles: jobItem.AdditionalFiles.slice(0),
            Id: getLocalId(serverInfo.Id, libraryItem.Id),
            SyncJobItemId: jobItem.SyncJobItemId
        };

        return Promise.resolve(item);
    }

    function getSubtitleSaveFileName(localItem, mediaPath, language, isForced, format) {

        var name = getNameWithoutExtension(mediaPath);

        if (language) {
            name += "." + language.toLowerCase();
        }

        if (isForced) {
            name += ".foreign";
        }

        name = name + "." + format.toLowerCase();

        var localPathArray = [localItem.LocalFolder, name];
        var localFilePath = filerepository.getPathFromArray(localPathArray);

        return localFilePath;

    }

    function getItemFileSize(path) {
        return filerepository.getItemFileSize(path);
    }

    function getNameWithoutExtension(path) {

        var fileName = path;

        var pos = fileName.lastIndexOf(".");

        if (pos > 0) {
            fileName = fileName.substring(0, pos);
        }

        return fileName;
    }

    function downloadFile(url, localItem) {

        return transfermanager.downloadFile(url, localItem);
    }

    function downloadSubtitles(url, fileName) {

        return transfermanager.downloadSubtitles(url, fileName);
    }

    function getImageUrl(serverId, itemId, imageType, index) {

        var pathArray = getImagePath(serverId, itemId, imageType, index);
        var relPath = pathArray.join('/');

        var prefix = 'ms-appdata:///local';
        return prefix + '/' + relPath;
    }

    function hasImage(serverId, itemId, imageType, index) {

        var pathArray = getImagePath(serverId, itemId, imageType, index);
        var localFilePath = filerepository.getFullLocalPath(pathArray);

        return filerepository.fileExists(localFilePath).then(function (exists) {
            // TODO: Maybe check for broken download when file size is 0 and item is not queued
            ////if (exists) {
            ////    if (!transfermanager.isDownloadFileInQueue(localFilePath)) {
            ////        // If file exists but 
            ////        exists = false;
            ////    }
            ////}

            return Promise.resolve(exists);
        }, function (err) {
            return Promise.resolve(false);
        });
    }

    function downloadImage(localItem, url, serverId, itemId, imageType, index) {

        var pathArray = getImagePath(serverId, itemId, imageType, index);
        var localFilePath = filerepository.getFullLocalPath(pathArray);

        if (!localItem.AdditionalFiles) {
            localItem.AdditionalFiles = [];
        }

        var fileInfo = {
            Path: localFilePath,
            Type: 'Image',
            Name: imageType + index.toString(),
            ImageType: imageType
        };

        localItem.AdditionalFiles.push(fileInfo);

        return transfermanager.downloadImage(url, localFilePath);
    }

    function isDownloadFileInQueue(path) {

        return transfermanager.isDownloadFileInQueue(path);
    }

    function translateFilePath(path) {
        return Promise.resolve(path);
    }

    // Helpers ***********************************************************

    function getDirectoryPath(item, server) {

        var parts = [];
        parts.push(server.Name);

        var itemtype = item.Type.toLowerCase();

        if (itemtype === 'episode') {

            parts.push("TV");

            var seriesName = item.SeriesName;
            if (seriesName) {
                parts.push(seriesName);
            }

            var seasonName = item.SeasonName;
            if (seasonName) {
                parts.push(seasonName);
            }

        } else if (itemtype === 'video') {

            parts.push("Videos");
            parts.push(item.Name);

        } else if (itemtype === 'audio') {

            parts.push("Music");

            var albumArtist = item.AlbumArtist;
            if (albumArtist) {
                parts.push(albumArtist);
            }

            if ((item.AlbumId) && (item.Album)) {
                parts.push(item.Album);
            }

        } else if (itemtype === 'photo') {

            parts.push("Photos");

            if ((item.AlbumId) && (item.Album)) {
                parts.push(item.Album);
            }

        }

        var finalParts = [];
        for (var i = 0; i < parts.length; i++) {

            finalParts.push(filerepository.getValidFileName(parts[i]));
        }

        return finalParts;
    }

    function getImagePath(serverId, itemId, imageType, index) {

        var parts = [];
        parts.push('Metadata');
        parts.push(serverId);
        parts.push('images');
        parts.push(itemId + '_' + imageType + '_' + index.toString() + '.png');

        var finalParts = [];
        for (var i = 0; i < parts.length; i++) {

            finalParts.push(filerepository.getValidFileName(parts[i]));
        }

        return finalParts;
    }

    function getLocalFileName(item, originalFileName) {

        var filename = originalFileName || item.Name;

        return filerepository.getValidFileName(filename);
    }

    function resyncTransfers() {
        return transfermanager.resyncTransfers();
    }

    function createGuid() {
        var d = new Date().getTime();
        if (window.performance && typeof window.performance.now === "function") {
            d += performance.now(); //use high-precision timer if available
        }
        var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            var r = (d + Math.random() * 16) % 16 | 0;
            d = Math.floor(d / 16);
            return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
        });
        return uuid;
    }

    return {

        getLocalItem: getLocalItem,
        saveOfflineUser: saveOfflineUser,
        deleteOfflineUser: deleteOfflineUser,
        recordUserAction: recordUserAction,
        getUserActions: getUserActions,
        deleteUserAction: deleteUserAction,
        deleteUserActions: deleteUserActions,
        getServerItemIds: getServerItemIds,
        removeLocalItem: removeLocalItem,
        addOrUpdateLocalItem: addOrUpdateLocalItem,
        createLocalItem: createLocalItem,
        downloadFile: downloadFile,
        downloadSubtitles: downloadSubtitles,
        hasImage: hasImage,
        downloadImage: downloadImage,
        getImageUrl: getImageUrl,
        translateFilePath: translateFilePath,
        getSubtitleSaveFileName: getSubtitleSaveFileName,
        getLocalItemById: getLocalItemById,
        getServerItems: getServerItems,
        getItemFileSize: getItemFileSize,
        isDownloadFileInQueue: isDownloadFileInQueue,
        getViews: getViews,
        getViewItems: getViewItems,
        resyncTransfers: resyncTransfers
    };
});