package timeext

import (
	"fmt"
	"time"
)

type OpenTimeRange struct {
	From *time.Time
	To   *time.Time
}

func (r OpenTimeRange) String() string {
	if r.From == nil && r.To == nil {
		return "[]"
	} else if r.From != nil && r.To != nil {
		return fmt.Sprintf("[%v - %v]", r.From, r.To)
	} else if r.From != nil {
		return fmt.Sprintf("[%v - *]", r.From)
	} else if r.To != nil {
		return fmt.Sprintf("[* - %v]", r.To)
	} else {
		return "[??]"
	}
}

func (r OpenTimeRange) Contains(v time.Time) bool {
	if r.From != nil && v.Before(*r.From) {
		return false
	}
	if r.To != nil && !v.Before(*r.To) {
		return false
	}
	return true
}

func NewOpenTimeRange(from *time.Time, to *time.Time) *OpenTimeRange {
	if from == nil && to == nil {
		return nil
	}
	return &OpenTimeRange{
		From: from,
		To:   to,
	}
}

func (r OpenTimeRange) ToMongoPipeline(key string) []interface{} {
	type bsonM map[string]interface{}
	type bsonE struct {
		Key   string
		Value interface{}
	}
	type bsonD []bsonE

	pipeline := make([]interface{}, 0)

	if r.From != nil {
		pipeline = append(pipeline, bsonD{{Key: "$match", Value: bsonM{key: bsonM{"$ne": nil, "$gt": r.From}}}})
	}
	if r.To != nil {
		pipeline = append(pipeline, bsonD{{Key: "$match", Value: bsonM{key: bsonM{"$ne": nil, "$lt": r.To}}}})
	}

	return pipeline
}

func (r *OpenTimeRange) AppendToMongoPipeline(pipeline []interface{}, key string) []interface{} {
	if r == nil {
		return pipeline
	}

	for _, v := range r.ToMongoPipeline(key) {
		pipeline = append(pipeline, v)
	}

	return pipeline
}