package org.atlasapi.persistence.media.entity;
import java.util.List;
import java.util.Set;
import org.atlasapi.media.entity.Broadcast;
import org.atlasapi.media.entity.Encoding;
import org.atlasapi.media.entity.Publisher;
import org.atlasapi.media.entity.Restriction;
import org.atlasapi.media.entity.Version;
import org.atlasapi.media.segment.SegmentEvent;
import org.atlasapi.media.segment.SegmentEventTranslator;
import org.atlasapi.persistence.ModelTranslator;
import org.joda.time.Duration;
import com.google.common.base.Function;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import com.google.common.collect.Sets;
import com.metabroadcast.common.ids.NumberToShortStringCodec;
import com.metabroadcast.common.persistence.translator.TranslatorUtils;
import com.mongodb.BasicDBList;
import com.mongodb.DBObject;
public class VersionTranslator implements ModelTranslator<Version> {
private static final String THREE_D_KEY = "threeD";
static final String ENCODINGS_KEY = "manifestedAs";
static final String BROADCASTS_KEY = "broadcasts";
private static final String PROVIDER_KEY = "provider";
private static final String SEGMENT_EVENTS_KEY = "segmentEvents";
private final IdentifiedTranslator descriptionTranslator = new IdentifiedTranslator();
private final BroadcastTranslator broadcastTranslator = new BroadcastTranslator();
private final EncodingTranslator encodingTranslator = new EncodingTranslator();
private final RestrictionTranslator restrictionTranslator = new RestrictionTranslator();
private final SegmentEventTranslator segmentEventTranslator;
public VersionTranslator(NumberToShortStringCodec idCodec) {
this.segmentEventTranslator = new SegmentEventTranslator(idCodec);
}
@Override
public Version fromDBObject(DBObject dbObject, Version entity) {
if (entity == null) {
entity = new Version();
}
descriptionTranslator.fromDBObject(dbObject, entity);
Integer durationInSeconds = (Integer) dbObject.get("duration");
if (durationInSeconds != null) {
entity.setDuration(Duration.standardSeconds(durationInSeconds));
}
if (dbObject.containsField(PROVIDER_KEY)) {
entity.setProvider(Publisher.fromKey((String) dbObject.get(PROVIDER_KEY)).requireValue());
}
entity.setPublishedDuration((Integer) dbObject.get("publishedDuration"));
entity.set3d(TranslatorUtils.toBoolean(dbObject, THREE_D_KEY));
if(dbObject.get("restriction") != null) {
entity.setRestriction(restrictionTranslator.fromDBObject((DBObject) dbObject.get("restriction"), null));
} else {
entity.setRestriction(new Restriction());
}
List<DBObject> list = TranslatorUtils.toDBObjectList(dbObject,BROADCASTS_KEY);
if (list != null && ! list.isEmpty()) {
Set<Broadcast> broadcasts = Sets.newLinkedHashSet();
for (DBObject object: list) {
Broadcast broadcast = broadcastTranslator.fromDBObject(object);
broadcasts.add(broadcast);
}
entity.setBroadcasts(broadcasts);
}
list = TranslatorUtils.toDBObjectList(dbObject,ENCODINGS_KEY);
if (list != null && ! list.isEmpty()) {
Set<Encoding> encodings = Sets.newHashSet();
for (DBObject object: list) {
Encoding encoding = encodingTranslator.fromDBObject(object, null);
encodings.add(encoding);
}
entity.setManifestedAs(encodings);
}
list = TranslatorUtils.toDBObjectList(dbObject, SEGMENT_EVENTS_KEY);
if (list != null && !list.isEmpty()) {
entity.setSegmentEvents(Lists.transform(list, new Function<DBObject, SegmentEvent>() {
@Override
public SegmentEvent apply(DBObject input) {
return segmentEventTranslator.fromDBObject(input, null);
}
}));
}
return entity;
}
@Override
public DBObject toDBObject(DBObject dbObject, Version entity) {
dbObject = descriptionTranslator.toDBObject(dbObject, entity);
TranslatorUtils.from(dbObject, "duration", entity.getDuration());
TranslatorUtils.from(dbObject, "publishedDuration", entity.getPublishedDuration());
TranslatorUtils.from(dbObject, THREE_D_KEY, entity.is3d());
if(entity.getRestriction() != null && entity.getRestriction().hasRestrictionInformation()) {
dbObject.put("restriction", restrictionTranslator.toDBObject(null, entity.getRestriction()));
}
if (entity.getProvider() != null) {
dbObject.put(PROVIDER_KEY, entity.getProvider().key());
}
if (! entity.getBroadcasts().isEmpty()) {
BasicDBList list = new BasicDBList();
for (Broadcast broadcast: sortByBroadcastTime(entity.getBroadcasts())) {
if (broadcast != null) {
list.add(broadcastTranslator.toDBObject(broadcast));
}
}
if (! list.isEmpty()) {
dbObject.put(BROADCASTS_KEY, list);
}
}
if (! entity.getManifestedAs().isEmpty()) {
BasicDBList list = new BasicDBList();
for (Encoding encoding: ENCODING_PERSISTENCE_ORDERING.immutableSortedCopy(entity.getManifestedAs())) {
if (encoding != null) {
list.add(encodingTranslator.toDBObject(null, encoding));
}
}
if (! list.isEmpty()) {
dbObject.put(ENCODINGS_KEY, list);
}
}
if (!entity.getSegmentEvents().isEmpty()) {
BasicDBList list = new BasicDBList();
for (SegmentEvent event : entity.getSegmentEvents()) {
if (event != null) {
list.add(segmentEventTranslator.toDBObject(null, event));
}
}
if (!list.isEmpty()) {
dbObject.put(SEGMENT_EVENTS_KEY, list);
}
}
return dbObject;
}
private List<Broadcast> sortByBroadcastTime(Set<Broadcast> broadcasts) {
return MOST_RECENT_FIRST.sortedCopy(broadcasts);
}
private static final Ordering<Broadcast> MOST_RECENT_FIRST = new Ordering<Broadcast>() {
@Override
public int compare(Broadcast a, Broadcast b) {
return ComparisonChain.start()
.compare(a.getTransmissionTime(), b.getTransmissionTime(), Ordering.natural().nullsLast())
.compare(a.getBroadcastOn(), b.getBroadcastOn(), Ordering.natural().nullsLast())
.compare(a.getSourceId(), b.getSourceId(), Ordering.natural().nullsLast())
.compare(a, b, Ordering.arbitrary())
.result();
}
};
private static final Ordering<Encoding> ENCODING_PERSISTENCE_ORDERING = new Ordering<Encoding>() {
@Override
public int compare(Encoding left, Encoding right) {
return ComparisonChain.start()
.compare(left.getCanonicalUri(), right.getCanonicalUri(), Ordering.natural().nullsLast())
.compare(left.getSigned(), right.getSigned(), Ordering.natural().nullsLast())
.compare(left.getVideoBitRate(), right.getVideoBitRate(), Ordering.natural().nullsLast())
.compare(left.getVideoHorizontalSize(), right.getVideoHorizontalSize(), Ordering.natural().nullsLast())
.compare(left.getVideoVerticalSize(), right.getVideoVerticalSize(), Ordering.natural().nullsLast())
.compare(left.getAudioDescribed(), right.getAudioDescribed(), Ordering.natural().nullsLast())
.compare(left.getDataContainerFormat(), right.getDataContainerFormat(), Ordering.natural().nullsLast())
.compare(left.getHasDOG(), right.getHasDOG(), Ordering.natural().nullsLast())
.result();
}
};
}