package feature

import (
	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/context"
	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/module"
	"gitlab.alibaba-inc.com/pai_biz_arch/pairec/recconf"
)

// Feature is a type for load user or item feature
type Feature struct {
	// featureDao use for load feature from specific dao, example:redis or hologres
	featureDao module.FeatureDao
	// featureTrans use for transform feature, specific operator by FeatureOp
	featureTrans []FeatureTrans
}

func LoadWithConfig(config recconf.FeatureLoadConfig) *Feature {
	f := &Feature{
		featureDao:   module.NewFeatureDao(config.FeatureDaoConf),
		featureTrans: make([]FeatureTrans, 0),
	}

	for _, conf := range config.Features {
		ft := NewFeatureTrans(conf.FeatureType, conf.FeatureName, conf.FeatureStore, conf.FeatureSource, conf.RemoveFeatureSource, conf.Normalizer)
		f.featureTrans = append(f.featureTrans, ft)
	}

	return f
}

func (f *Feature) LoadFeatures(user *module.User, items []*module.Item, context *context.RecommendContext) {
	f.featureDao.FeatureFetch(user, items, context)
	for _, trans := range f.featureTrans {
		trans.FeatureTran(user, items, context)
	}
}

// func (f *Feature) TransFeatures(user *module.User, items []*module.Item, context *context.RecommendContext) {
// }

const (
	SOURCE_USER = "user"
	SOURCE_ITEM = "item"
)

type FeatureTrans interface {
	FeatureTran(user *module.User, items []*module.Item, context *context.RecommendContext)
}

type featureTrans struct {
	// featureType         string
	featureOp           FeatureOp
	featureName         string
	featureSource       string
	removeFeatureSource bool   // delete feature source
	featureStore        string // user or item
	normalizer          Normalizer
}

func NewFeatureTrans(t, name, store string, source string, remove bool, normalizer string) FeatureTrans {
	return &featureTrans{
		// featureType: t,
		featureOp:           NewFeatureOp(t),
		featureName:         name,
		featureStore:        store,
		featureSource:       source,
		removeFeatureSource: remove,
		normalizer:          NewNormalizer(normalizer),
	}
}

func (f *featureTrans) FeatureTran(user *module.User, items []*module.Item, context *context.RecommendContext) {
	if f.featureStore == SOURCE_ITEM {
		for _, item := range items {
			f.featureOp.ItemTransOp(f.featureName, f.featureSource, f.removeFeatureSource, f.normalizer, user, item, context)
		}

	} else {
		f.featureOp.UserTransOp(f.featureName, f.featureSource, f.removeFeatureSource, f.normalizer, user, context)
	}
}
