package org.openlmis.report.model.dto;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.openlmis.core.utils.DateUtil;
import org.openlmis.stockmanagement.domain.StockCard;
import org.openlmis.stockmanagement.domain.StockCardEntry;
import org.openlmis.stockmanagement.domain.StockCardEntryKV;
import java.util.*;
import static com.google.common.collect.FluentIterable.from;
import static com.google.common.collect.Lists.newArrayList;
@Data
@NoArgsConstructor
public class FacilityProductReportEntry {
private String productName;
private String facilityName;
private long productQuantity;
private Date soonestExpiryDate;
private Date lastSyncDate;
private String code;
public static final String EXPIRATION_DATES = "expirationdates";
public FacilityProductReportEntry(StockCard stockCard, Date endTime) {
if (endTime == null) {
endTime = new Date();
}
this.productName = stockCard.getProduct().getPrimaryName();
List<StockCardEntry> stockCardEntryList = filterEntryByDate(stockCard, endTime);
this.productQuantity = calculateQuantity(stockCardEntryList);
assignSoonestExpirationDate(stockCardEntryList);
this.code = stockCard.getProduct().getCode();
}
private String getExpirationDateFromStockCardEntry(StockCardEntry entry){
Optional<StockCardEntryKV> stockCardEntryKVOptional = from(entry.getKeyValues()).firstMatch(new Predicate<StockCardEntryKV>() {
@Override
public boolean apply(StockCardEntryKV input) {
return EXPIRATION_DATES.equalsIgnoreCase(input.getKeyColumn());
}
});
if (stockCardEntryKVOptional.isPresent()){
return stockCardEntryKVOptional.get().getValueColumn();
}
return StringUtils.EMPTY;
}
private void assignSoonestExpirationDate(List<StockCardEntry> stockCardEntryList) {
if (stockCardEntryList == null || stockCardEntryList.size() == 0) {
return;
}
StockCardEntry lastEntry = from(stockCardEntryList).first().get();
String expirationDates = getExpirationDateFromStockCardEntry(lastEntry);
if (!StringUtils.isEmpty(expirationDates)) {
String[] dateStrings = expirationDates.split(",");
Optional<Date> soonestDate = from(sortExpirationDate(dateStrings)).last();
if (soonestDate.isPresent()) {
this.soonestExpiryDate = soonestDate.get();
}
}
}
private ImmutableList<Date> sortExpirationDate(String[] dateStrings) {
return from(newArrayList(dateStrings)).transform(new Function<String, Date>() {
@Override
public Date apply(String input) {
return DateUtil.parseDate(input,DateUtil.FORMAT_DATE_TIME_DAY_MONTH_YEAR );
}
}).toSortedList(new Comparator<Date>() {
@Override
public int compare(Date o1, Date o2) {
return o2.compareTo(o1);
}
});
}
private List<StockCardEntry> filterEntryByDate(final StockCard stockCard, final Date date) {
return from(stockCard.getEntries()).filter(new Predicate<StockCardEntry>() {
@Override
public boolean apply(StockCardEntry input) {
return !DateUtils.truncate(input.getCreatedDate(), Calendar.DATE).after(date);
}
}).toList();
}
private long calculateQuantity(List<StockCardEntry> stockCardEntryList) {
long result = 0;
for (StockCardEntry entry : stockCardEntryList) {
result += entry.getQuantity();
}
return result;
}
}