package operator

import (
	"fmt"

	"go.mongodb.org/mongo-driver/bson"
)

type Regex struct {
	Key   string
	Value string
}

func (re Regex) MarshalBSON() ([]byte, error) {
	return filterMarshal("$regex", re.Key, re.Value)
}

type FilterIn struct {
	Key    string
	Values []interface{}
}

func NewFilterIn(key string, values interface{}) FilterIn {
	fi := FilterIn{Key: key}
	switch values.(type) {
	case []interface{}:
		fi.Values = values.([]interface{})
		if len(fi.Values) == 0 {
			return NewFilterIn(key, nil)
		}
	case []string:
		value := values.([]string)
		fi.Values = make([]interface{}, len(value))
		for i := range value {
			fi.Values[i] = value[i]
		}
		if len(fi.Values) == 0 {
			return NewFilterIn(key, nil)
		}
	case []int:
		value := values.([]int)
		fi.Values = make([]interface{}, len(value))
		for i := range value {
			fi.Values[i] = value[i]
		}
		if len(fi.Values) == 0 {
			return NewFilterIn(key, nil)
		}
	case nil:
		fi.Key = ""
	default:
		panic(fmt.Sprintf("cannot convert values to filter in: %T", values))
	}
	return fi
}

func (fi FilterIn) MarshalBSON() ([]byte, error) {
	return filterMarshal("$in", fi.Key, fi.Values)
}

func filterMarshal(op, key string, value interface{}) ([]byte, error) {
	if len(key) == 0 {
		return bson.Marshal(map[string]interface{}{})
	}
	m := map[string]map[string]interface{}{
		key: map[string]interface{}{
			op: value,
		},
	}
	return bson.Marshal(m)
}
