'use strict';

import {generateUUID, chunkArray} from "./utils";
import {serializeError} from "serialize-error";

let user = function () {
    return {
        updateUserSelf: (data = {}) => {
            return this.__privates.auth.__client
                .then(client => client.apis.user.updateMyself({...(data.lastRoomId && {lastRoomId:data.lastRoomId})},{requestBody: {...data}}))
        },

        updateUser: (data = {}) => {
            return this.__privates.auth.__client
                .then(client => client.apis.user.updateUser({id: data.id, lastRoomId: data.lastRoomId}, {requestBody: {displayname: data.displayname, bio: data.bio, permissions: data.permissions}}));
        },

        uploadAvatar: (file, lastRoomId) => {
            let id = generateUUID();
            return this.__privates.auth.__client
                .then(client => Promise.all([client, client.apis.user.initiateMyAvatarUpload({id})]))
                .then(([client, response]) => Promise.all([client, client.http({url: response.data.signedUrl, method: response.data.httpMethod, headers: {"Content-Type":file.type}, body:file})]))
                .then(([client, response]) => client.apis.user.publishMyAvatar({id, lastRoomId}))
                ;
        },
        unsetAvatar: (lastRoomId) => {
            return this.__privates.auth.__client
                .then((client) => client.apis.user.publishMyAvatar({lastRoomId}));
        },
        uploadReaction: (files) => {
            let id = generateUUID();
            return this.__privates.auth.__client
                .then(client => Promise.all([client, client.apis.reaction.initiateReactionUpload({id:id, segmentCount: files.length || 0})]))
                .then(([client, response]) => Promise.all([client, ...response.data.signedUrlSegments.map((url, index) => client.http({url, method: response.data.httpMethod, headers: {"Content-Type":files[index].type}, body:files[index]}))]))
                .then(([client]) => client.apis.reaction.processReaction({id:id, type: 'concat'}))
                .then(response => response.data.key)
                ;
        },
        uploadVideo: (roomId, files, privateAttributes = {}, customAttributes = {}, customPrice) => {
            let id = generateUUID();
            return this.__privates.auth.__client
                .then(client => Promise.all([client, client.apis.video.initiateVideoUpload({id, segmentCount:  files.length || 0})]))
                .then(([client, response]) => Promise.all([client, response.data.signedUrlSegments.reduce((acc, url, index) => acc.then(() => client.http({url, method: response.data.httpMethod, headers: {"Content-Type":files[index].type}, body:files[index]})), Promise.resolve())]))
                .then(([client]) => client.apis.video.publishVideo({_id:id, roomId, customPrice}, {requestBody:{_id:id, roomId, privateAttributes, customAttributes, customPrice}}))
        },

        publishVideo: (roomId, id, privateAttributes = {}, customAttributes = {}, customPrice) => {
            return this.__privates.auth.__client
                .then(client => client.apis.video.publishVideo({_id:id, roomId, customPrice}, {requestBody:{_id:id, roomId, privateAttributes, customAttributes, customPrice}}))
        },

        getReactionById: (id) => {
            return this.__privates.auth.__client
                .then(client => client.apis.reaction.getReactionById({id}))
        },

        getReactions: ({userId, roomId, type, size, startKey, includeUserModels = false} = {}) => {
            let apiParams = {
                ...(roomId && {roomId}),
                ...(userId && {userId}),
                ...(size && {size}),
                ...(startKey && {startKey}),
                includeUserModels,
                type
            };
            return this.__privates.auth.__client
                .then(client => client.apis.reaction.getReactions(apiParams))
        },

        getVideoById: (id) => {
            return this.__privates.auth.__client
                .then(client => client.apis.video.getVideoById({id}))
        },

        getVideos: ({roomId, userId, type, size, startKey, ids, includeUserModels = false, includeRoomQueueStatus, filter} = {}) => {
            return chunkArray(ids, 50)
                .reduce((promiseChain, idsChunk) => {
                    return promiseChain.then(chainResponse => {
                        let apiParams = {
                            ...(roomId && {roomId}),
                            ...(userId && {userId}),
                            ...(size && {size}),
                            ...(idsChunk?.length && {ids: idsChunk.join(',')}),
                            ...(startKey && {startKey}),
                            ...(includeRoomQueueStatus && {includeRoomQueueStatus}),
                            ...(filter && Object.keys(filter).length && {filter: JSON.stringify(filter)}),
                            includeUserModels,
                            type
                        };
                        return this.__privates.auth.__client
                            .then(client => client.apis.video.getVideos(apiParams))
                            .then(response => type === 'ids' ? {
                                data: {
                                    items: [...chainResponse.data.items, ...response.data.items],
                                    size: chainResponse.data.size + response.data.size,
                                    startKey: null,
                                    users: [...chainResponse.data.users, ...(response.data.users ?? [])],
                                },
                            } : response);
                    });
                }, Promise.resolve({data: {items: [], size: 0, startKey: null, users: []}}));
        },

        getVideoListFilters: (roomId) => {
            return this.__privates.auth.__client
                .then(client => client.apis.video.getVideoListFilters({roomId}));
        },

        deleteVideo: (id) => {
            return this.__privates.auth.__client
                .then(client => client.apis.video.deleteVideo({id}))
        },

        getUserSelf: () => {
            return this.__privates.auth.__client
                .then(client => client.apis.user.getUserMyself())
        },
        getUserById: (id) => {
            return this.__privates.auth.__client
                .then(client => client.apis.user.getUserById({id}))
        },
        getUsersByIds: ({ids = [], size = null, startKey = null } = {}) => {
            return chunkArray(ids, 50)
                .reduce((promiseChain, idsChunk) => {
                    return promiseChain.then(chainResponse => {
                        let apiParams = {
                            type : 'ids',
                            ...(size && {size}),
                            ...(idsChunk?.length && {ids: idsChunk.join(',')}),
                            ...(startKey && {startKey})
                        };
                        return this.__privates.auth.__client
                            .then(client => client.apis.user.getUsers(apiParams))
                            .then(response => ({
                                data: {
                                    items: [...chainResponse.data.items, ...response.data.items],
                                    size: chainResponse.data.size + response.data.size,
                                    startKey: null,
                                },
                            }));
                    });
                }, Promise.resolve({data: {items: [], size: 0, startKey: null}}));
        },
        getUserList:  ({type = 'instanceType', roomId, ids, size = 20, startKey = null}) => {
            return chunkArray(ids, 50)
                .reduce((promiseChain, idsChunk) => {
                    return promiseChain.then(chainResponse => {
                        let apiParams = {
                            type,
                            ...(roomId && {roomId}),
                            ...(idsChunk?.length && {ids: idsChunk.join(',')}),
                            ...(size && !ids && {size}),
                            ...(startKey && {startKey})
                        };
                        return this.__privates.auth.__client
                            .then(client => client.apis.user.getUsers(apiParams))
                            .then(response => type === 'ids' ? ({
                                data: {
                                    items: [...chainResponse.data.items, ...response.data.items],
                                    size: chainResponse.data.size + response.data.size,
                                    startKey: null,
                                },
                            }) : response);
                    });
                }, Promise.resolve({data: {items: [], size: 0, startKey: null}}));
        },

        //TODO:deprecated
        track: ({eventType = 'ERROR', message} = {}) => {
            return this.__privates.auth.__client
                .then(client => client.apis.wt.track({},{
                    requestBody:{
                        "eventType": eventType,
                        "appType": "web",
                        "deviceType": `desktop${navigator.maxTouchPoints ? '/touch' : ''}`,
                        "os": navigator.platform,
                        "browser": navigator.userAgent,
                        "domain": location.host,
                        "url": location.href,
                        "message": serializeError(message)
                    }
                }));
        },

        //TODO:deprecated
        getTranslation: ({namespace = 'wt'} = {}) => {
            return this.__privates.auth.__client
                .then(client => client.apis.system.getTranslation({namespace}))
        },

        //TODO:deprecated
        getConfig: ({instanceType = this.__instanceType, domain = location.hostname} = {}) => {
            return this.__privates.auth.__client
                .then(client => client.apis.system.getConfig({instanceType, domain}));
        },

        //TODO:deprecated
        getIntegrationPublic: (type, data = {}) => {
            return this.__privates.auth.__client
                .then(client => client.apis.system.integrationPublic({type}, {requestBody:{...data}}))
        },

        //TODO:deprecated
        updateConfig: (data = {}) => {
            return this.__privates.auth.__client
                .then(client => client.apis.wt.updateConfig({id: data.instanceType || this.__instanceType},{requestBody:{...data}}));
        },

        //TODO:deprecated
        admin: (data = {}) => {
            return this.__privates.auth.__client
                .then(client => client.apis.wt.admin({},{requestBody:{instanceType : this.__instanceType, ...data}}));
        },

        //TODO:deprecated
        analytics: ({action, startKey = null, limit = 20} = {}) => {

            let apiParams = {
                action,
                limit,
                ...(startKey && {startKey})
            };
            return this.__privates.auth.__client
                .then(client => client.apis.wt.analytics({},{requestBody:{instanceType : this.__instanceType, ...apiParams}}));

        }
    }
};

export default user;
