package rpc

import (
	"../log"
	"../mod"
	"../nt"
	"bytes"
	"errors"
	"github.com/gorilla/rpc/json"
	"go.uber.org/zap"
	"net/http"
)

var (
	ErrFailedFindUserAgent = errors.New("failed to find agent by user")
	ErrFailedFindLobby     = errors.New("failed to find agent by id")
)

func MakeRpcUrl(rpcAddr string) string {
	return "http://" + rpcAddr + "/rpc"
}

// 根据命令请求，选择一个或多个逻辑服务器
func GetAllLobbiesRpcUrl(cmd string) ([]string, error) {
	var r []string
	for _, conf := range nt.DynConf.Lobbies {
		r = append(r, MakeRpcUrl(conf.RpcAddr))
	}
	return r, nil //测试返回所有服务器
}

func BroadCastToLobbies(args *RpcArgs, res *RpcResult) error {
	addrs, err := GetAllLobbiesRpcUrl(args.Cmd)
	if nil != err {
		return err
	}
	for _, addr := range addrs {
		err = RpcRequest(addr, args, res)
		if nil != err {
			log.Error("BroadCastToLobbies", zap.String("cmd", args.Cmd), zap.String("addr", addr), zap.Error(err))
		}
	}
	return nil
}

func BroadCastToOneLobby(args *RpcArgs, res *RpcResult) error {
	addrs, err := GetAllLobbiesRpcUrl(args.Cmd)
	if nil != err {
		return err
	}
	err = RpcRequest(addrs[0], args, res)
	if nil != err {
		log.Error("BroadCastToLobbies", zap.String("cmd", args.Cmd), zap.String("addr", addrs[0]), zap.Error(err))
	}
	return nil
}


func GetUserAgentRpcUrl(guid uint64) (string, error) {
	agent, err := mod.GetUserAgent(guid)
	if nil != err {
		return "", err
	}
	for _, conf := range nt.DynConf.Lobbies {
		if conf.Id == agent {
			return MakeRpcUrl(conf.RpcAddr), nil
		}
	}
	return "", ErrFailedFindUserAgent
}

func GetThisRpcUrl() string {
	return MakeRpcUrl(nt.InstConf.RpcAddr)
}

func GetLobbyById(id uint64) (string, error) {
	for _, conf := range nt.DynConf.Lobbies {
		if conf.Id == id {
			return MakeRpcUrl(conf.RpcAddr), nil
		}
	}
	return "", ErrFailedFindLobby
}

// 发送 rpc 请求，并同步返回结果。
func RpcRequest(url string, args *RpcArgs, res *RpcResult) error {
	msg, err := json.EncodeClientRequest("RpcService.Request", args)
	if nil != err {
		nt.Log.Debug("encode", zap.Error(err))
		return err
	}
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(msg))
	if nil != err {
		nt.Log.Debug("request", zap.Error(err))
		return err
	}
	req.Header.Set("Content-Type", "application/json")
	client := new(http.Client)
	resp, err := client.Do(req)
	if nil != err {
		nt.Log.Debug("do", zap.Error(err))
		return err
	}
	defer resp.Body.Close()

	err = json.DecodeClientResponse(resp.Body, res)
	if nil != err {
		nt.Log.Debug("decode", zap.Error(err))
		return err
	}
	return nil
}
