package module

import (
	"strconv"
	"strings"

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

const (
	Feature_Store_User    = "user"
	Feature_Store_Item    = "item"
	Feature_Type_Sequence = "sequence_feature"
)

// FeatureDao is interface, it define FeatureFetch to featch feature from implement
type FeatureDao interface {
	FeatureFetch(user *User, items []*Item, context *context.RecommendContext)
}

// NewFeatureDao create FeatureDao from config
// config.AdapterType is decide the implement
func NewFeatureDao(config recconf.FeatureDaoConfig) FeatureDao {
	if config.AdapterType == recconf.DaoConf_Adapter_Redis {
		return NewFeatureRedisDao(config)
	} else if config.AdapterType == recconf.DaoConf_Adapter_Hologres {
		return NewFeatureHologresDao(config)
	} else if config.AdapterType == recconf.DaoConf_Adapter_TableStore {
		return NewFeatureTablestoreDao(config)
	} else if config.AdapterType == recconf.DaoConf_Adapter_Mysql {
		return NewFeatureMysqlDao(config)
	}

	panic("not found FeatureDao implement")
}

type FeatureBaseDao struct {
	featureKey   string // use the value of key to featch data
	featureStore string // user or item
	featureType  string

	// sequence feature has under attribute
	sequenceLength      int
	sequenceName        string
	sequenceEvent       string
	sequenceDelim       string
	sequenceDimFields   []string
	sequencePlayTimeMap map[string]float64
}

func NewFeatureBaseDao(config *recconf.FeatureDaoConfig) *FeatureBaseDao {
	dao := FeatureBaseDao{
		featureKey:   config.FeatureKey,
		featureStore: config.FeatureStore,
		featureType:  config.FeatureType,

		sequenceLength:      config.SequenceLength,
		sequenceName:        config.SequenceName,
		sequenceEvent:       config.SequenceEvent,
		sequenceDelim:       config.SequenceDelim,
		sequencePlayTimeMap: make(map[string]float64, 0),
	}

	if config.SequencePlayTime != "" {
		playTimes := strings.Split(config.SequencePlayTime, ";")
		for _, eventTime := range playTimes {
			strs := strings.Split(eventTime, ":")
			if len(strs) == 2 {
				if t, err := strconv.ParseFloat(strs[1], 64); err == nil {
					dao.sequencePlayTimeMap[strs[0]] = t
				}
			}
		}
	}
	if config.SequenceDimFields != "" {
		dao.sequenceDimFields = strings.Split(config.SequenceDimFields, ",")
	}
	return &dao
}
