package service

import (
	"context"
	"reflect"

	"git.loafle.net/commons/configuration-go"
	cda "git.loafle.net/commons/di-go/annotation"
	cdr "git.loafle.net/commons/di-go/registry"
	logging "git.loafle.net/commons/logging-go"
	crc "git.loafle.net/commons/rpc-go/client"
	occn "git.loafle.net/overflow/commons-go/config/noauthprobe"
	"git.loafle.net/overflow/commons-go/core/util"
	"git.loafle.net/overflow/probe/client/auth"
	"git.loafle.net/overflow/probe/config"

	// For annotation
	_ "git.loafle.net/overflow/probe/auth/annotation"
)

var NoAuthProbeServiceType = reflect.TypeOf((*NoAuthProbeService)(nil))

func init() {
	cdr.RegisterType(NoAuthProbeServiceType)
}

type NoAuthProbeService struct {
	cda.TypeAnnotation `annotation:"@overflow:AuthRPCService()"`

	Config       *config.Config `annotation:"@Resource(name='Config')"`
	AuthConfig   *occn.Auth     `annotation:"@Resource(name='AuthConfig')"`
	AuthDoneChan chan error     `annotation:"@Resource(name='AuthDoneChan')"`

	client *crc.Client
}

func (s *NoAuthProbeService) InitService() error {
	client, err := auth.New(s.HandleResponse, s)
	if nil != err {
		return err
	}
	s.client = client

	return nil
}

func (s *NoAuthProbeService) StartService() error {
	if err := s.client.Start(); nil != err {
		return err
	}

	return nil
}

func (s *NoAuthProbeService) StopService() {
	if err := s.client.Stop(context.Background()); nil != err {
		logging.Logger().Error(err)
	}
}

func (s *NoAuthProbeService) DestroyService() {
	s.client = nil
}

func (s *NoAuthProbeService) Accept(probeKey string) error {
	logging.Logger().Infof("accepted by central")

	n := util.Now()
	s.AuthConfig.AcceptedDate = &n
	if err := configuration.Save(s.AuthConfig, config.NoAuthProbeConfigFilePath(), true); nil != err {
		logging.Logger().Error(err)
		s.AuthDoneChan <- err
		return nil
	}

	s.Config.Probe.Key = &probeKey
	if err := configuration.Save(s.Config, config.ProbeConfigFilePath(), true); nil != err {
		logging.Logger().Error(err)
		s.AuthDoneChan <- err
		return nil
	}

	s.AuthDoneChan <- nil
	return nil
}

func (s *NoAuthProbeService) Deny() error {
	logging.Logger().Infof("denied by central")
	n := util.Now()
	s.AuthConfig.DeniedDate = &n
	if err := configuration.Save(s.AuthConfig, config.NoAuthProbeConfigFilePath(), true); nil != err {
		logging.Logger().Error(err)
		s.AuthDoneChan <- err
		return nil
	}

	s.AuthDoneChan <- nil
	return nil
}

func (s *NoAuthProbeService) HandleResponse(method string, param string) {
	switch method {
	case occn.HTTPResponseHeaderValue_NoAuthProbe_Method_TempProbeKey:
		logging.Logger().Infof("registered by central")
		s.AuthConfig.TempKey = &param
		if err := configuration.Save(s.AuthConfig, config.NoAuthProbeConfigFilePath(), true); nil != err {
			logging.Logger().Error(err)
			s.AuthDoneChan <- err
			return
		}

	case occn.HTTPResponseHeaderValue_NoAuthProbe_Method_Accept:
		s.Accept(param)
	case occn.HTTPResponseHeaderValue_NoAuthProbe_Method_Deny:
		s.Deny()
	}

}
