package com.bao.lc.site.s3.ai;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.chain.Context;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.bao.lc.ResMgr;
import com.bao.lc.site.s3.TdUtils;
import com.bao.lc.site.s3.bean.ComparableFilter;
import com.bao.lc.site.s3.bean.PassengerInfo;
import com.bao.lc.site.s3.bean.TrainTicketInfo;
import com.bao.lc.site.s3.params.TdPNames;
import com.bao.lc.site.s3.params.TdParams;
import com.bao.lc.util.SortFilter;
public class TrainTicketSelector
{
private static Log log = LogFactory.getLog(TrainTicketSelector.class);
private List<TrainTicketInfo> tickets = null;
private Context context = null;
private int passengerCount = 1;
private List<SortFilter<TrainTicketInfo>> filter = null;
public TrainTicketSelector(List<TrainTicketInfo> ticketList, Context context)
{
this.tickets = new ArrayList<TrainTicketInfo>(ticketList.size());
this.tickets.addAll(ticketList);
// @TODO: get from context
this.context = context;
this.passengerCount = MapUtils.getIntValue(context, TdPNames.PARAM_PASSENGER_COUNT, 1);
TrainTicketSortFilterBuilder fb = new TrainTicketSortFilterBuilder(context);
this.filter = fb.build();
}
public TrainTicketInfo select()
{
for(Iterator<TrainTicketInfo> iter = tickets.iterator(); iter.hasNext();)
{
TrainTicketInfo ticket = iter.next();
for(SortFilter<TrainTicketInfo> cond : filter)
{
if(!cond.accept(ticket))
{
iter.remove();
log.info("The ticket has been filtered by filter: " + cond.getCategory()
+ ", ticket=" + ticket);
String message = MessageFormat.format(
ResMgr.getString("td.msg.ticket.filtered"),
TdUtils.getFilterCatName(cond.getCategory()), ticket.toString());
TdParams.getUI(context).info(message);
break;
}
}
}
if(tickets.isEmpty())
{
log.info("All the tickets has been filtered.");
return null;
}
Collections.sort(tickets, new TrainTicketComparator(filter, passengerCount));
TrainTicketInfo selectedTicket = tickets.get(0);
updatePassengerSeatClass(context, selectedTicket);
return selectedTicket;
}
private void updatePassengerSeatClass(Context context, TrainTicketInfo ticket)
{
SortFilter<TrainTicketInfo> seatClassCond = null;
for(SortFilter<TrainTicketInfo> cond : filter)
{
if(cond.getCategory() == TrainTicketInfo.CAT_SEAT_CLASS)
{
seatClassCond = cond;
break;
}
}
if(seatClassCond == null)
{
log.warn("Can't find the seat class filter");
return;
}
List<Integer> seatClassList = (List<Integer>) seatClassCond.getValues();
ComparableFilter columnFilter = ticket.getColumn(seatClassCond.getCategory(),
seatClassList, this.passengerCount);
List<Integer> seatCountList = (List<Integer>) columnFilter.getValue();
String passengerSeatClass = TdUtils.getSeatClassValue(TrainTicketInfo.HARD_SEAT);
for(int i = 0, size = seatCountList.size(); i < size; i++)
{
int seatCount = seatCountList.get(i);
if(seatCount >= this.passengerCount)
{
int seatClass = seatClassList.get(i);
passengerSeatClass = TdUtils.getSeatClassValue(seatClass);
log.info("Select seatClass: index=" + seatClass + ", value=" + passengerSeatClass);
break;
}
}
List<PassengerInfo> passengers = TdParams.getPassengerList(context);
for(PassengerInfo passenger: passengers)
{
passenger.seatClass = passengerSeatClass;
}
}
private static class TrainTicketComparator implements Comparator<TrainTicketInfo>
{
private List<SortFilter<TrainTicketInfo>> conds = null;
private int passengerCount = 1;
public TrainTicketComparator(List<SortFilter<TrainTicketInfo>> conds, int passengerCount)
{
this.conds = conds;
this.passengerCount = passengerCount;
}
@Override
public int compare(TrainTicketInfo o1, TrainTicketInfo o2)
{
for(SortFilter<TrainTicketInfo> cond : conds)
{
Comparable value1 = o1.getColumn(cond.getCategory(), cond.getValues(),
passengerCount);
Comparable value2 = o2.getColumn(cond.getCategory(), cond.getValues(),
passengerCount);
if(value1 != null && value2 != null)
{
int diff = value1.compareTo(value2);
if(diff != 0)
{
return diff;
}
}
}
return 0;
}
}
}