package auth

import (
	"fmt"
	"net/http"
	"reflect"

	cdr "git.loafle.net/commons/di-go/registry"
	logging "git.loafle.net/commons/logging-go"
	crc "git.loafle.net/commons/rpc-go/client"
	csc "git.loafle.net/commons/server-go/client"
	cur "git.loafle.net/commons/util-go/reflect"
	occn "git.loafle.net/overflow/commons-go/config/noauthprobe"
	"git.loafle.net/overflow/probe/auth/info"
	"git.loafle.net/overflow/probe/client"
	"git.loafle.net/overflow/probe/config"
)

func New(responseHandler func(method string, param string), services ...interface{}) (*crc.Client, error) {
	config := config.GetConfig()
	if nil == config {
		return nil, fmt.Errorf("Config is not available")
	}
	authConfig := getAuthConfig()
	if nil == authConfig {
		return nil, fmt.Errorf("AuthConfig is not available")
	}

	connector, err := client.NewConnector("Auth", occn.HTTPEntry_Auth)
	if nil != err {
		return nil, err
	}

	connector.RequestHeader = func() http.Header {
		header := make(map[string][]string)
		switch authConfig.State() {
		case occn.AuthStateTypeRegisterd:
			header[occn.HTTPRequestHeaderKey_NoAuthProbe_Method] = []string{occn.HTTPRequestHeaderValue_NoAuthProbe_Method_Connect}
			header[occn.HTTPRequestHeaderKey_NoAuthProbe_TempProbeKey] = []string{*authConfig.TempKey}
		default:
			rh, err := info.GetRegistHeader(config.Account.APIKey)
			if nil != err {
				logging.Logger().Error(err)
				return header
			}
			header[occn.HTTPRequestHeaderKey_NoAuthProbe_Method] = []string{occn.HTTPRequestHeaderValue_NoAuthProbe_Method_Regist}
			header[occn.HTTPRequestHeaderKey_NoAuthProbe_Info] = []string{rh}
		}
		return header
	}
	connector.ResponseHandler = func(res *http.Response) {
		responseMethod := res.Header.Get(occn.HTTPResponseHeaderKey_NoAuthProbe_Method)
		responseMethodParam := res.Header.Get(occn.HTTPResponseHeaderKey_NoAuthProbe_Method_Param)

		if nil != responseHandler {
			responseHandler(responseMethod, responseMethodParam)
		}
	}

	connector.OnDisconnected = func(connector csc.Connector) {
		logging.Logger().Debugf("Client[%s] has been disconnected", connector.GetName())
	}

	return client.New("Auth", connector, services), nil
}

func getAuthConfig() *occn.Auth {
	_config, err := cdr.GetInstanceByName("AuthConfig")
	if nil != err {
		logging.Logger().Error(err)
		return nil
	}
	config, ok := _config.(*occn.Auth)
	if !ok {
		_, pkg, n := cur.GetTypeInfo(reflect.TypeOf(_config))
		logging.Logger().Errorf("Cannot convert [%s]%s to Config type", pkg, n)
		return nil
	}

	return config
}
