package sep

// FilterByID returns ListSEP with specified ID.
func (lsep ListSEP) FilterByID(id uint64) ListSEP {
	predicate := func(rsep RecordSEP) bool {
		return rsep.ID == id
	}

	return lsep.FilterFunc(predicate)
}

// FilterByName returns ListSEP with specified Name.
func (lsep ListSEP) FilterByName(name string) ListSEP {
	predicate := func(rsep RecordSEP) bool {
		return rsep.Name == name
	}

	return lsep.FilterFunc(predicate)
}

// FilterByObjStatus returns ListSEP with specified ObjStatus.
func (lsep ListSEP) FilterByObjStatus(objStatus string) ListSEP {
	predicate := func(rsep RecordSEP) bool {
		return rsep.ObjStatus == objStatus
	}

	return lsep.FilterFunc(predicate)
}

// FilterByTechStatus returns ListSEP with specified TechStatus.
func (lsep ListSEP) FilterByTechStatus(techStatus string) ListSEP {
	predicate := func(rsep RecordSEP) bool {
		return rsep.TechStatus == techStatus
	}

	return lsep.FilterFunc(predicate)
}

// FilterByType returns ListSEP with specified Type.
func (lsep ListSEP) FilterByType(sepType string) ListSEP {
	predicate := func(rsep RecordSEP) bool {
		return rsep.Type == sepType
	}

	return lsep.FilterFunc(predicate)
}

// FilterFunc allows filtering ListSEP based on user-specified predicate.
func (lsep ListSEP) FilterFunc(predicate func(RecordSEP) bool) ListSEP {
	var result ListSEP

	for _, item := range lsep.Data {
		if predicate(item) {
			result.Data = append(result.Data, item)
		}
	}

	result.EntryCount = uint64(len(result.Data))

	return result
}

// FindOne returns first found RecordSEP
// If none was found, returns an empty struct.
func (lsep ListSEP) FindOne() RecordSEP {
	if len(lsep.Data) == 0 {
		return RecordSEP{}
	}

	return lsep.Data[0]
}

// FilterBySEPID returns ListAvailableSEP with the specified SEPID.
func (sl ListAvailableSEP) FilterBySEPID(sepID uint64) ListAvailableSEP {
	predicate := func(sd SEPData) bool {
		return sd.SEPID == sepID
	}

	return sl.FilterFunc(predicate)
}

// FilterBySEPName returns ListAvailableSEP with the specified SEPName.
func (sl ListAvailableSEP) FilterBySEPName(SEPName string) ListAvailableSEP {
	predicate := func(sd SEPData) bool {
		return sd.SEPName == SEPName
	}

	return sl.FilterFunc(predicate)
}

// FilterBySEPType returns ListAvailableSEP with the specified SEPType.
func (sl ListAvailableSEP) FilterBySEPType(SEPType string) ListAvailableSEP {
	predicate := func(sd SEPData) bool {
		return sd.SEPType == SEPType
	}

	return sl.FilterFunc(predicate)
}

// FilterByPoolType returns ListAvailableSEP where at least one pool has the specified type.
func (sl ListAvailableSEP) FilterByPoolType(poolType string) ListAvailableSEP {
	predicate := func(sd SEPData) bool {
		for _, pool := range sd.Pools {
			for _, pt := range pool.Types {
				if pt == poolType {
					return true
				}
			}
		}
		return false
	}

	return sl.FilterFunc(predicate)
}

// FilterBySystemPool returns ListAvailableSEP where at least one pool is a system pool.
func (sl ListAvailableSEP) FilterBySystemPool(isSystem bool) ListAvailableSEP {
	predicate := func(sd SEPData) bool {
		for _, pool := range sd.Pools {
			if pool.System == isSystem {
				return true
			}
		}
		return false
	}

	return sl.FilterFunc(predicate)
}

// FilterFunc allows filtering ListAvailableSEP based on a user-defined predicate.
func (sl ListAvailableSEP) FilterFunc(predicate func(SEPData) bool) ListAvailableSEP {
	var result ListAvailableSEP

	for _, item := range sl.Data {
		if predicate(item) {
			result.Data = append(result.Data, item)
		}
	}

	result.EntryCount = uint64(len(result.Data))

	return result
}

// FindOne returns the first found SEPData.
// If nothing is found, returns an empty struct.
func (sl ListAvailableSEP) FindOne() SEPData {
	if len(sl.Data) == 0 {
		return SEPData{}
	}

	return sl.Data[0]
}
