package eas

import (
	"errors"

	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/log"
	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/recconf"
)

const (
	Eas_Processor_FM      = "ALINK_FM"
	Eas_Processor_PMML    = "PMML"
	Eas_Processor_TF      = "TensorFlow"
	Eas_Processor_EASYREC = "EasyRec"
	Eas_Processor_LINUCB  = "Linucb"
)

type EasModel struct {
	retryTimes int
	name       string
	request    IEasRequest
}

func NewEasModel(name string) *EasModel {
	return &EasModel{name: name, retryTimes: 2}
}
func (m *EasModel) Init(conf *recconf.AlgoConfig) error {
	if conf.EasConf.Processor == Eas_Processor_PMML {
		req := PMMLRequest{}
		req.SetUrl(conf.EasConf.Url)
		req.SetAuth(conf.EasConf.Auth)
		req.SetTimeout(conf.EasConf.Timeout)
		req.SetResponseFunc(conf.EasConf.ResponseFuncName)
		m.request = &req

		if conf.EasConf.RetryTimes > 0 {
			m.retryTimes = conf.EasConf.RetryTimes
		}
		return nil
	} else if conf.EasConf.Processor == Eas_Processor_TF {
		req := TFRequest{}
		req.SetUrl(conf.EasConf.Url)
		req.SetAuth(conf.EasConf.Auth)
		req.SetSignatureName(conf.EasConf.SignatureName)
		req.SetTimeout(conf.EasConf.Timeout)
		req.SetResponseFunc(conf.EasConf.ResponseFuncName)
		if len(conf.EasConf.Outputs) > 0 {
			req.SetOutputs(conf.EasConf.Outputs)
		}
		m.request = &req

		if conf.EasConf.RetryTimes > 0 {
			m.retryTimes = conf.EasConf.RetryTimes
		}
		return nil
	} else if conf.EasConf.Processor == Eas_Processor_FM {
		req := NewFMRequest()
		req.SetUrl(conf.EasConf.Url)
		req.SetAuth(conf.EasConf.Auth)
		req.SetTimeout(conf.EasConf.Timeout)
		req.SetResponseFunc(conf.EasConf.ResponseFuncName)
		m.request = req

		if conf.EasConf.RetryTimes > 0 {
			m.retryTimes = conf.EasConf.RetryTimes
		}
		return nil

	} else if conf.EasConf.Processor == Eas_Processor_EASYREC {
		req := EasyrecRequest{}
		req.SetUrl(conf.EasConf.Url)
		req.SetAuth(conf.EasConf.Auth)
		req.SetTimeout(conf.EasConf.Timeout)
		req.SetResponseFunc(conf.EasConf.ResponseFuncName)
		m.request = &req

		if conf.EasConf.RetryTimes > 0 {
			m.retryTimes = conf.EasConf.RetryTimes
		}
		return nil
	} else if conf.EasConf.Processor == Eas_Processor_LINUCB {
		req := LincubRequest{}
		req.SetUrl(conf.EasConf.Url)
		req.SetAuth(conf.EasConf.Auth)
		req.SetTimeout(conf.EasConf.Timeout)
		req.SetResponseFunc(conf.EasConf.ResponseFuncName)
		m.request = &req

		if conf.EasConf.RetryTimes > 0 {
			m.retryTimes = conf.EasConf.RetryTimes
		}
		return nil

	}

	return errors.New("not found eas Processor:" + conf.EasConf.Processor)
}
func (m *EasModel) Run(algoData interface{}) (interface{}, error) {
	retryTimes := m.retryTimes

	var (
		data interface{}
		err  error
	)

	for {
		retryTimes--
		data, err = m.request.Invoke(algoData)
		if err != nil && retryTimes == 0 {
			return data, err
		} else if err == nil {
			break
		} else if err != nil {
			log.Warning("eas request fail :" + err.Error())
		}
	}

	if m.request.GetResponseFunc() != nil {
		return m.request.GetResponseFunc()(data)
	}

	return data, err
}
