package references

import (
	"git.perx.ru/perxis/perxis-go/pkg/items"
	pb "git.perx.ru/perxis/perxis-go/proto/references"
	"go.mongodb.org/mongo-driver/bson"
)

type Reference struct {
	ID           string `json:"id" bson:"id" mapstructure:"id"`
	CollectionID string `json:"collection_id" bson:"collection_id" mapstructure:"collection_id"`
	Disabled     bool   `json:"disabled,omitempty" bson:"disabled,omitempty" mapstructure:"disabled"`
}

func (r *Reference) MarshalBSON() ([]byte, error) {
	d := bson.D{
		{Key: "id", Value: r.ID},
		{Key: "collection_id", Value: r.CollectionID},
	}

	if r.Disabled {
		d = append(d, bson.E{Key: "disabled", Value: true})
	}

	return bson.Marshal(d)
}

func (r *Reference) ToExprMap() map[string]interface{} {
	return map[string]interface{}{
		"collection_id": r.CollectionID,
		"id":            r.ID,
	}
}

func ReferenceFromPB(refPB *pb.Reference) *Reference {
	if refPB == nil {
		return nil
	}
	return &Reference{
		ID:           refPB.Id,
		CollectionID: refPB.CollectionId,
		Disabled:     refPB.Disabled,
	}
}

func ReferenceFromItem(item *items.Item) *Reference {
	if item == nil {
		return nil
	}

	return &Reference{
		ID:           item.ID,
		CollectionID: item.CollectionID,
	}
}

func ReferenceToPB(ref *Reference) *pb.Reference {
	if ref == nil {
		return nil
	}
	return &pb.Reference{
		Id:           ref.ID,
		CollectionId: ref.CollectionID,
		Disabled:     ref.Disabled,
	}
}

func ReferenceListFromPB(refsPB []*pb.Reference) []*Reference {
	if refsPB == nil {
		return nil
	}

	list := make([]*Reference, 0, len(refsPB))
	for _, refPB := range refsPB {
		list = append(list, ReferenceFromPB(refPB))
	}
	return list
}

func ReferenceListToPB(refs []*Reference) []*pb.Reference {
	if refs == nil {
		return nil
	}

	list := make([]*pb.Reference, 0, len(refs))
	for _, ref := range refs {
		list = append(list, ReferenceToPB(ref))
	}
	return list
}

func (r *Reference) String() string {
	if r == nil {
		return ""
	}
	return r.CollectionID + "." + r.ID
}

func (r *Reference) Equal(r1 *Reference) bool {
	return r == r1 || r != nil && r1 != nil && r.CollectionID == r1.CollectionID && r.ID == r1.ID && r.Disabled == r1.Disabled
}

func EqualArrays(sr1, sr2 []*Reference) bool {
	if len(sr1) != len(sr2) {
		return false
	}
	for i, r := range sr1 {
		if !r.Equal(sr2[i]) {
			return false
		}
	}
	return true
}

func (r *Reference) IsValid() bool {
	return r != nil && r.ID != "" && r.CollectionID != "" && !r.Disabled
}