package localserver

import (
	"context"
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

const (
	EDIT_DEFAULT_RIGHTS        = "edit_default_rights"
	EDIT_USERS_RIGHTS          = "edit_users_rights"
	LIST_ZONE_MEMBERS          = "list_zone_members"
	LIST_ZONE_MEMBERS_RESPONSE = "list_zone_members_response"
	GET_USER                   = "get_user"
	GET_DEFAULT_RIGHTS         = "get_default_rights"
	MODIFY_USER_CHAT_RIGHTS    = "modify_user_chat_rights"
	ADD_KNOWN_CHAT             = "add_known_chat"
	REMOVE_KNOWN_CHAT          = "remove_known_chat"
	ADD_KNOWN_AUDIO_CHANNEL    = "add_known_audio_channel"
	REMOVE_KNOWN_AUDIO_CHANNEL = "remove_known_audio_channel"
	ADD_KNOWN_VIDEO_CHANNEL    = "add_known_video_channel"
	REMOVE_KNOWN_VIDEO_CHANNEL = "remove_known_video_channel"
	ADD_USER                   = "add_user"
	REMOVE_USER                = "remove_user"
)

const (
	NEW_ZONE_USER             = "new_zone_user"
	GET_CURRENT_USER_RESPONSE = "get_current_user_response"
	GET_USER_RESPONSE         = "get_user_response"
	REMOVED_ZONE_USER         = "removed_zone_user"
	DEFAULT_RIGHTS_EDITED     = "default_rights_edited"
	USER_RIGHTS_EDITED        = "user_rights_edited"
)

type ZoneUsersHandler struct {
	ZoneId               string
	ZoneMembersId        []string
	DataChannels         map[string]*DataChannel
	UserDataChannels     map[string]*DataChannel
	UserDataChannelsFlag *uint32
	Flag                 *uint32
	Publishers           []<-chan *ZoneRequest
	DB                   *ZoneUsersDBHandler
	reqChans             []chan<- *ZoneRequest
}

type ZoneMember struct {
	ID     string          `json:"id"`
	Admin  bool            `json:"admin"`
	Owner  bool            `json:"owner"`
	Config *ZoneUserConfig `json:"config"`
}

type ZoneUserConfig struct {
	DefaultChatRights         *ChatRights         `json:"defaultChatsRights"`
	DefaultAudioChannelRights *AudioChannelRights `json:"defaultAudioChannelsRights"`
	DefaultVideoChannelRights *VideoChannelRights `json:"defaultVideoChannelsRights"`
	DefaultMediaRights        *MediaRights        `json:"defaultMediaRights"`
	DefaultFileRights         *FileRights         `json:"defaultFileRights"`
}

func NewZoneUsersHandler(zoneId string, owner string, authorizedMembers []string, dataChannels map[string]*DataChannel, flag *uint32) (zoneUsersHandler *ZoneUsersHandler, err error) {
	_, err = os.ReadDir(filepath.Join(dataPath, "data", "zones", zoneId, "users"))
	var zoneUsersDBHandler *ZoneUsersDBHandler
	if err != nil {
		if os.IsNotExist(err) {
			logger.Printf("creating chat directory for zone %s...\n", zoneId)
			mkdirErr := os.MkdirAll(filepath.Join(dataPath, "data", "zones", zoneId, "users"), 0700)
			if mkdirErr != nil {
				return nil, mkdirErr
			}
			file, ferr := os.Create(filepath.Join(dataPath, "data", "zones", zoneId, "users", "usersConfig.json"))
			defer func() {
				_ = file.Close()
			}()
			if ferr != nil {
				return nil, ferr
			}
			baseConfig := ZoneUserConfig{
				DefaultChatRights:         NewChatRights(true),
				DefaultAudioChannelRights: NewAudioChannelRights(true),
				DefaultVideoChannelRights: NewVideoChannelRights(true),
				DefaultMediaRights:        NewMediaRights(true),
				DefaultFileRights:         NewFileRights(true),
			}
			bs, jsonErr := json.Marshal(baseConfig)
			if jsonErr != nil {
				return nil, jsonErr
			}
			if _, writeErr := file.WriteString(string(bs)); writeErr != nil {
				return nil, writeErr
			}
			zoneUsersDBHandler, err = NewZoneUsersDBHandler(zoneId, owner, authorizedMembers, true)
			if err != nil {
				return
			}
		} else {
			return
		}
	} else {
		zoneUsersDBHandler, err = NewZoneUsersDBHandler(zoneId, owner, authorizedMembers, false)
	}
	if err != nil {
		return
	}
	userDCFlag := uint32(0)
	zoneUsersHandler = &ZoneUsersHandler{
		ZoneId:               zoneId,
		DataChannels:         dataChannels,
		UserDataChannels:     make(map[string]*DataChannel),
		UserDataChannelsFlag: &userDCFlag,
		ZoneMembersId:        authorizedMembers,
		Flag:                 flag,
		DB:                   zoneUsersDBHandler,
	}
	return
}

func (zuh *ZoneUsersHandler) Init(ctx context.Context, authorizedMembers []string) (err error) {
	users, err := zuh.DB.ListUsers(0, 1000)
	if err != nil {
		return
	}
	logger.Println(authorizedMembers)
	for _, user := range users {
		var contain bool
		for _, member := range authorizedMembers {
			if user.ID == member {
				contain = true
				break
			}
		}
		if !contain {
			logger.Println("userId", user.ID)
			if rerr := zuh.RemoveUser(user.ID); rerr != nil {
				logger.Println(rerr)
			}
			go func(userId string) {
				for _, rc := range zuh.reqChans {
					logger.Println("------------------------ sending to req chan ------------------------")
					rc <- &ZoneRequest{
						ReqType: string(REMOVED_ZONE_AUTHORIZED_MEMBER),
						From:    "node",
						Payload: map[string]interface{}{
							"userId": userId,
						},
					}
				}
			}(user.ID)
		}
	}
	return
}

func (zuh *ZoneUsersHandler) sendDataChannelMessage(reqType string, from string, to string, payload map[string]interface{}) (<-chan struct{}, <-chan error) {
	done, errCh := make(chan struct{}, 10), make(chan error, 10)
	go func() {
		if err := atomicallyExecute(zuh.UserDataChannelsFlag, func() (err error) {
			if _, ok := zuh.UserDataChannels[to]; ok {
				bs, jsonErr := json.Marshal(&ZoneResponse{
					Type:    reqType,
					From:    from,
					To:      to,
					Payload: payload,
				})
				if jsonErr != nil {
					return jsonErr
				}
				err = zuh.UserDataChannels[to].DataChannel.SendText(string(bs))
			}
			return
		}); err != nil {
			errCh <- err
			return
		}
		done <- struct{}{}
		logger.Printf("sending %v done\n", payload)
	}()
	return done, errCh
}

func (zuh *ZoneUsersHandler) Subscribe(ctx context.Context, publisher <-chan *ZoneRequest) (reqChan chan *ZoneRequest, done chan struct{}, errCh chan error) {
	reqChan, done, errCh = make(chan *ZoneRequest), make(chan struct{}), make(chan error)
	zuh.reqChans = append(zuh.reqChans, reqChan)
	go func() {
		for {
			select {
			case <-ctx.Done():
				done <- struct{}{}
				return
			case req := <-publisher:
				if err := zuh.handleZoneRequest(ctx, req); err != nil {
					errCh <- err
				}
			}
		}
	}()
	return
}

func (zuh *ZoneUsersHandler) AddUser(userId string) (err error) {
	bs, err := os.ReadFile(filepath.Join(dataPath, "data", "zones", zuh.ZoneId, "users", "usersConfig.json"))
	if err != nil {
		return
	}
	var baseUserConfig ZoneUserConfig
	if err = json.Unmarshal(bs, &baseUserConfig); err != nil {
		return
	}
	newUser := &User{
		ID:                   userId,
		Name:                 userId,
		ChatRights:           baseUserConfig.DefaultChatRights,
		AudioChannelRights:   baseUserConfig.DefaultAudioChannelRights,
		VideoChannelRights:   baseUserConfig.DefaultVideoChannelRights,
		MediaRights:          baseUserConfig.DefaultMediaRights,
		FileRights:           baseUserConfig.DefaultFileRights,
		KnownChatsId:         []string{},
		KnownAudioChannelsId: []string{},
		KnownVideoChannelsId: make([]string, 0),
		KnownMediaFolderId:   make([]string, 0),
		KnownFileFolderId:    make([]string, 0),
	}
	if err = zuh.DB.AddNewUser(newUser); err != nil {
		return
	}
	err = atomicallyExecute(zuh.Flag, func() (err error) {
		users, err := zuh.DB.ListUsers(0, 10000)
		if err != nil {
			return
		}
		bs, jsonErr := json.Marshal(&ZoneResponse{
			Type: NEW_ZONE_USER,
			From: "node",
			To:   "user",
			Payload: map[string]interface{}{
				"user": newUser,
			},
		})
		if jsonErr != nil {
			return jsonErr
		}
		for _, user := range users {
			if _, ok := zuh.DataChannels[user.ID]; ok {
				_ = zuh.DataChannels[user.ID].DataChannel.SendText(string(bs))
			}
		}
		return
	})
	return
}

func (zuh *ZoneUsersHandler) RemoveUser(userId string) (err error) {
	if err = zuh.DB.DeleteUser(userId); err != nil {
		return
	}
	err = atomicallyExecute(zuh.Flag, func() (err error) {
		users, err := zuh.DB.ListUsers(0, 10000)
		if err != nil {
			return
		}
		bs, jsonErr := json.Marshal(&ZoneResponse{
			Type: REMOVED_ZONE_USER,
			From: "node",
			To:   "user",
			Payload: map[string]interface{}{
				"userId": userId,
			},
		})
		if jsonErr != nil {
			return jsonErr
		}
		if _, ok := zuh.DataChannels[userId]; ok {
			_ = zuh.DataChannels[userId].DataChannel.SendText(string(bs))
		}
		for _, user := range users {
			if _, ok := zuh.DataChannels[user.ID]; ok {
				_ = zuh.DataChannels[user.ID].DataChannel.SendText(string(bs))
			}
		}
		return
	})
	return
}

func (zuh *ZoneUsersHandler) AddKnownChat(chatId string, userId string) (err error) {
	user, err := zuh.DB.GetUser(userId)
	if err != nil {
		return
	}
	for _, id := range user.KnownChatsId {
		if id == chatId {
			err = fmt.Errorf("user already know channel %s", chatId)
			return
		}
	}
	user.KnownChatsId = append(user.KnownChatsId, chatId)
	if err = zuh.DB.ModifyUser(userId, user); err != nil {
		return
	}
	return
}

func (zuh *ZoneUsersHandler) RemoveKnownChat(chatId string, userId string) (err error) {
	user, err := zuh.DB.GetUser(userId)
	if err != nil {
		return
	}
	var index int
	var contain bool
	for i, id := range user.KnownChatsId {
		if id == chatId {
			index = i
			contain = true
			break
		}
	}
	if !contain {
		err = fmt.Errorf("does not know this chat")
		return
	}
	if len(user.KnownChatsId) < 2 {
		user.KnownChatsId = make([]string, 0)
	} else {
		user.KnownChatsId = append(user.KnownChatsId[:index], user.KnownChatsId[index+1:]...)
	}
	err = zuh.DB.ModifyUser(userId, user)
	return
}

func (zuh *ZoneUsersHandler) AddKnownAudioChannel(channelId string, userId string) (err error) {
	logger.Println("added new audio channel", channelId, userId)
	user, err := zuh.DB.GetUser(userId)
	if err != nil {
		return
	}
	for _, id := range user.KnownAudioChannelsId {
		if id == channelId {
			err = fmt.Errorf("user already know channel %s", channelId)
			return
		}
	}
	user.KnownAudioChannelsId = append(user.KnownAudioChannelsId, channelId)
	if err = zuh.DB.ModifyUser(userId, user); err != nil {
		return
	}
	return
}

func (zuh *ZoneUsersHandler) RemoveKnownAudioChannel(channelId string, userId string) (err error) {
	user, err := zuh.DB.GetUser(userId)
	if err != nil {
		return
	}
	var index int
	var contain bool
	for i, id := range user.KnownAudioChannelsId {
		if id == channelId {
			index = i
			contain = true
			break
		}
	}
	if !contain {
		err = fmt.Errorf("does not know this chat")
		return
	}
	if len(user.KnownAudioChannelsId) < 2 {
		user.KnownAudioChannelsId = make([]string, 0)
	} else {
		user.KnownAudioChannelsId = append(user.KnownAudioChannelsId[:index], user.KnownAudioChannelsId[index+1:]...)
	}
	err = zuh.DB.ModifyUser(userId, user)
	return
}

func (zuh *ZoneUsersHandler) AddKnownVideoChannel(channelId string, userId string) (err error) {
	logger.Println("added new audio channel", channelId, userId)
	user, err := zuh.DB.GetUser(userId)
	if err != nil {
		return
	}
	for _, id := range user.KnownVideoChannelsId {
		if id == channelId {
			err = fmt.Errorf("user already know channel %s", channelId)
			return
		}
	}
	user.KnownVideoChannelsId = append(user.KnownVideoChannelsId, channelId)
	if err = zuh.DB.ModifyUser(userId, user); err != nil {
		return
	}
	return
}

func (zuh *ZoneUsersHandler) RemoveKnownVideoChannel(channelId string, userId string) (err error) {
	user, err := zuh.DB.GetUser(userId)
	if err != nil {
		return
	}
	var index int
	var contain bool
	for i, id := range user.KnownVideoChannelsId {
		if id == channelId {
			index = i
			contain = true
			break
		}
	}
	if !contain {
		err = fmt.Errorf("does not know this chat")
		return
	}
	if len(user.KnownVideoChannelsId) < 2 {
		user.KnownVideoChannelsId = make([]string, 0)
	} else {
		user.KnownVideoChannelsId = append(user.KnownVideoChannelsId[:index], user.KnownVideoChannelsId[index+1:]...)
	}
	err = zuh.DB.ModifyUser(userId, user)
	return
}

func (zuh *ZoneUsersHandler) AddKnownFolder(folderId string, userId string) (err error) {
	logger.Println("added new known folder", folderId, userId)
	user, err := zuh.DB.GetUser(userId)
	if err != nil {
		return
	}
	for _, id := range user.KnownFileFolderId {
		if id == folderId {
			err = fmt.Errorf("user already know channel %s", folderId)
			return
		}
	}
	user.KnownVideoChannelsId = append(user.KnownVideoChannelsId, folderId)
	if err = zuh.DB.ModifyUser(userId, user); err != nil {
		return
	}
	return
}

func (zuh *ZoneUsersHandler) RemoveKnownFolder(folderId string, userId string) (err error) {
	user, err := zuh.DB.GetUser(userId)
	if err != nil {
		return
	}
	var index int
	var contain bool
	for i, id := range user.KnownFileFolderId {
		if id == folderId {
			index = i
			contain = true
			break
		}
	}
	if !contain {
		err = fmt.Errorf("does not know this chat")
		return
	}
	if len(user.KnownFileFolderId) < 2 {
		user.KnownFileFolderId = make([]string, 0)
	} else {
		user.KnownFileFolderId = append(user.KnownFileFolderId[:index], user.KnownFileFolderId[index+1:]...)
	}
	err = zuh.DB.ModifyUser(userId, user)
	return
}

func (zuh *ZoneUsersHandler) GetDefaultRights(userId string) (err error) {
	bs, err := os.ReadFile(filepath.Join(dataPath, "data", "zones", zuh.ZoneId, "users", "usersConfig.json"))
	if err != nil {
		return
	}
	var defaultRights ZoneUserConfig
	if err = json.Unmarshal(bs, &defaultRights); err != nil {
		return
	}
	d, e := zuh.sendDataChannelMessage(GET_DEFAULT_RIGHTS, "node", userId, map[string]interface{}{
		"defaultRights": defaultRights,
	})
	select {
	case <-d:
	case err = <-e:
	}
	return
}

func (zuh *ZoneUsersHandler) EditDefaultRights(defaultChatRights *ChatRights, defaultAudioChannelRights *AudioChannelRights, defaultVideoChannelRights *VideoChannelRights, defaultMediaRights *MediaRights, defaultFileRights *FileRights) (err error) {
	bs, err := os.ReadFile(filepath.Join(dataPath, "data", "zones", zuh.ZoneId, "users", "usersConfig.json"))
	if err != nil {
		return
	}
	var baseUserConfig ZoneUserConfig
	if err = json.Unmarshal(bs, &baseUserConfig); err != nil {
		return
	}
	baseUserConfig.DefaultChatRights = defaultChatRights
	baseUserConfig.DefaultAudioChannelRights = defaultAudioChannelRights
	baseUserConfig.DefaultVideoChannelRights = defaultVideoChannelRights
	baseUserConfig.DefaultMediaRights = defaultMediaRights
	baseUserConfig.DefaultFileRights = defaultFileRights
	bs, err = json.Marshal(baseUserConfig)
	if err != nil {
		return
	}
	file, err := os.OpenFile(filepath.Join(dataPath, "data", "zones", zuh.ZoneId, "users", "usersConfig.json"), os.O_WRONLY|os.O_TRUNC, os.ModeAppend)
	defer func() {
		_ = file.Close()
	}()
	if err != nil {
		return
	}
	if _, err = file.WriteString(string(bs)); err != nil {
		return
	}
	for _, member := range zuh.ZoneMembersId {
		done, err := zuh.sendDataChannelMessage(DEFAULT_RIGHTS_EDITED, "node", member, map[string]interface{}{
			"defaultRights": baseUserConfig,
		})
		select {
		case <-done:
		case e := <-err:
			logger.Println(e)
		}
	}
	return
}

func (zuh *ZoneUsersHandler) EditUsersRights(users []interface{}, chatRights *ChatRights, audioChannelRights *AudioChannelRights, videoChannelRights *VideoChannelRights, mediaRights *MediaRights, fileRights *FileRights) (err error) {
	for _, u := range users {
		if user, ok := u.(string); ok {
			if err = zuh.editUserRights(user, chatRights, audioChannelRights, videoChannelRights, mediaRights, fileRights); err != nil {
				logger.Println(err)
			}
		}
	}
	return
}

func (zuh *ZoneUsersHandler) editUserRights(userId string, chatRights *ChatRights, audioChannelRights *AudioChannelRights, videoChannelRights *VideoChannelRights, mediaRights *MediaRights, fileRights *FileRights) (err error) {
	user, err := zuh.DB.GetUser(userId)
	if err != nil {
		return
	}
	user.ChatRights = chatRights
	user.AudioChannelRights = audioChannelRights
	user.VideoChannelRights = videoChannelRights
	user.MediaRights = mediaRights
	user.FileRights = fileRights
	if err = zuh.DB.ModifyUser(userId, user); err != nil {
		return
	}
	for _, id := range zuh.ZoneMembersId {
		d, e := zuh.sendDataChannelMessage(USER_RIGHTS_EDITED, "node", userId, map[string]interface{}{
			"userId": id,
			"user":   user,
		})
		select {
		case <-d:
		case err = <-e:
		}
	}
	return
}

func (zuh *ZoneUsersHandler) handleDataChannel(ctx context.Context, dc *DataChannel) (catched bool) {
	var label string
	_ = atomicallyExecute(dc.l, func() (err error) {
		label = dc.DataChannel.Label()
		return
	})
	if strings.Contains(label, "user_data") {
		command := strings.Split(label, "|")
		catched = true
		_ = atomicallyExecute(zuh.UserDataChannelsFlag, func() (err error) {
			zuh.UserDataChannels[command[1]] = dc
			return
		})
		dc.DataChannel.OnOpen(func() {
			done, errCh := zuh.sendDataChannelMessage("user_zone_init", zuh.ZoneId, command[1], map[string]interface{}{})
			select {
			case <-done:
				fmt.Println("zone init sent")
			case err := <-errCh:
				fmt.Println(err)
			}
		})
		dc.DataChannel.OnClose(func() {
			fmt.Println("closing gratefully user dc...")
			_ = atomicallyExecute(zuh.UserDataChannelsFlag, func() (err error) {
				delete(zuh.UserDataChannels, command[1])
				return
			})
		})
		dc.DataChannel.OnError(func(err error) {
			fmt.Println("error in user dc...")
			_ = atomicallyExecute(zuh.UserDataChannelsFlag, func() (err error) {
				delete(zuh.UserDataChannels, command[1])
				return
			})
		})
	}
	return
}

func (zuh *ZoneUsersHandler) handleZoneRequest(ctx context.Context, req *ZoneRequest) (err error) {
	logger.Println("got request in zone users handler", req)
	switch req.ReqType {
	case EDIT_DEFAULT_RIGHTS:
		if _, ok := req.Payload["defaultRights"]; !ok {
			err = fmt.Errorf("no field defaultRights in request payload")
			return
		}
		bs, jsonErr := json.Marshal(req.Payload["defaultRights"])
		if jsonErr != nil {
			return jsonErr
		}
		var config ZoneUserConfig
		if err = json.Unmarshal(bs, &config); err != nil {
			err = fmt.Errorf("the defaultRights payload dont match ZoneFSEntity struct pattern : %v", err)
			return
		}
		err = zuh.EditDefaultRights(config.DefaultChatRights, config.DefaultAudioChannelRights, config.DefaultVideoChannelRights, config.DefaultMediaRights, config.DefaultFileRights)
	case EDIT_USERS_RIGHTS:
		if err = verifyFieldsSliceInterface(req.Payload, "users"); err != nil {
			return
		}
		if _, ok := req.Payload["defaultRights"]; !ok {
			err = fmt.Errorf("no field defaultRights in request payload")
			return
		}
		bs, jsonErr := json.Marshal(req.Payload["defaultRights"])
		if jsonErr != nil {
			return jsonErr
		}
		var config ZoneUserConfig
		if err = json.Unmarshal(bs, &config); err != nil {
			err = fmt.Errorf("the defaultRights payload dont match ZoneFSEntity struct pattern : %v", err)
			return
		}
		err = zuh.EditUsersRights(req.Payload["users"].([]interface{}), config.DefaultChatRights, config.DefaultAudioChannelRights, config.DefaultVideoChannelRights, config.DefaultMediaRights, config.DefaultFileRights)
	case REMOVE_USER:
		if err = verifyFieldsString(req.Payload, "userId"); err != nil {
			return
		}
		err = zuh.RemoveUser(req.Payload["userId"].(string))
	case ADD_USER:
		if err = verifyFieldsString(req.Payload, "userId"); err != nil {
			return
		}
		err = zuh.AddUser(req.Payload["userId"].(string))
	case REMOVE_KNOWN_CHAT:
		if err = verifyFieldsString(req.Payload, "chatId", "userId"); err != nil {
			return
		}
		err = zuh.RemoveKnownChat(req.Payload["chatId"].(string), req.Payload["userId"].(string))
	case ADD_KNOWN_CHAT:
		if err = verifyFieldsString(req.Payload, "chatId", "userId"); err != nil {
			return
		}
		err = zuh.AddKnownChat(req.Payload["chatId"].(string), req.Payload["userId"].(string))
	case REMOVE_KNOWN_AUDIO_CHANNEL:
		if err = verifyFieldsString(req.Payload, "channelId", "userId"); err != nil {
			return
		}
		err = zuh.RemoveKnownAudioChannel(req.Payload["channelId"].(string), req.Payload["userId"].(string))
	case ADD_KNOWN_AUDIO_CHANNEL:
		if err = verifyFieldsString(req.Payload, "channelId", "userId"); err != nil {
			return
		}
		err = zuh.AddKnownAudioChannel(req.Payload["channelId"].(string), req.Payload["userId"].(string))
	case REMOVE_KNOWN_VIDEO_CHANNEL:
		if err = verifyFieldsString(req.Payload, "channelId", "userId"); err != nil {
			return
		}
		err = zuh.RemoveKnownVideoChannel(req.Payload["channelId"].(string), req.Payload["userId"].(string))
	case ADD_KNOWN_VIDEO_CHANNEL:
		if err = verifyFieldsString(req.Payload, "channelId", "userId"); err != nil {
			return
		}
		err = zuh.AddKnownVideoChannel(req.Payload["channelId"].(string), req.Payload["userId"].(string))
	case GET_DEFAULT_RIGHTS:
		if err = verifyFieldsString(req.Payload, "userId"); err != nil {
			return
		}
		err = zuh.GetDefaultRights(req.Payload["userId"].(string))
	case GET_USER:
		if err = verifyFieldsString(req.Payload, "userId"); err != nil {
			return
		}
		if _, ok := req.Payload["init"]; !ok {
			err = fmt.Errorf("no field init in req payload for get user")
			return
		}
		if _, ok := req.Payload["init"].(bool); !ok {
			err = fmt.Errorf("field init is of wrong type")
			return
		}
		user, err := zuh.DB.GetUser(req.Payload["userId"].(string))
		if err != nil {
			return err
		}
		logger.Println("get user done")

		if req.Payload["init"].(bool) {
			done, errCh := zuh.sendDataChannelMessage(GET_CURRENT_USER_RESPONSE, "node", req.Payload["userId"].(string), map[string]interface{}{
				"user": user,
			})
			select {
			case <-done:
			case err = <-errCh:
				return err
			}

		} else {
			done, errCh := zuh.sendDataChannelMessage(GET_USER_RESPONSE, "node", req.Payload["userId"].(string), map[string]interface{}{
				"user": user,
			})
			select {
			case <-done:
			case err = <-errCh:
				return err
			}
		}
	case LIST_ZONE_MEMBERS:
		user, err := zuh.DB.GetUser(req.From)
		if err != nil {
			return err
		}
		users, err := zuh.DB.ListUsers(0, 1000)
		if err != nil {
			return err
		}
		usersIds := []*ZoneMember{}
		groupCounter := 0
		if user.Admin || user.Owner {
			for _, user := range users {
				if groupCounter >= 8 {
					done, errCh := zuh.sendDataChannelMessage(LIST_ZONE_MEMBERS_RESPONSE, zuh.ZoneId, req.From, map[string]interface{}{
						"done":  false,
						"users": usersIds,
					})
					select {
					case <-done:
						logger.Println("send get user done")
					case err = <-errCh:
						return err
					}
					groupCounter = 0
					usersIds = []*ZoneMember{}
				}
				usersIds = append(usersIds, &ZoneMember{
					ID:    user.ID,
					Admin: user.Admin,
					Owner: user.Owner,
					Config: &ZoneUserConfig{
						DefaultChatRights:         user.ChatRights,
						DefaultAudioChannelRights: user.AudioChannelRights,
						DefaultVideoChannelRights: user.VideoChannelRights,
						DefaultMediaRights:        user.MediaRights,
						DefaultFileRights:         user.FileRights,
					},
				})
				groupCounter++
			}
		} else {
			for _, user := range users {
				if groupCounter >= 8 {
					done, errCh := zuh.sendDataChannelMessage(LIST_ZONE_MEMBERS_RESPONSE, zuh.ZoneId, req.From, map[string]interface{}{
						"done":  false,
						"users": usersIds,
					})
					select {
					case <-done:
						logger.Println("send get user done")
					case err = <-errCh:
						return err
					}
					groupCounter = 0
					usersIds = []*ZoneMember{}
				}
				usersIds = append(usersIds, &ZoneMember{
					ID:    user.ID,
					Admin: user.Admin,
					Owner: user.Owner,
				})
				groupCounter++
			}
		}
		logger.Println("get user done")
		done, errCh := zuh.sendDataChannelMessage(LIST_ZONE_MEMBERS_RESPONSE, zuh.ZoneId, req.From, map[string]interface{}{
			"done":  true,
			"users": usersIds,
		})
		select {
		case <-done:
			logger.Println("send get user done")
		case err = <-errCh:
			return err
		}
	case MODIFY_USER_CHAT_RIGHTS:
	}
	return
}
