package tv.pluto.mongo.utils;

import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.GsonBuilder;
import com.mongodb.BasicDBObject;
import com.mongodb.client.model.Filters;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
import org.bson.conversions.Bson;
import tv.pluto.mongo.entities.transcodejobs.Fragments;
import tv.pluto.mongo.entities.transcodejobs.Transcode;
import tv.pluto.mongo.entities.transcodejobs.TranscodeJobs;
import tv.pluto.mongo.utils.json.SkipDeserialisation;

public class TranscodeJobsUtils extends MongoUtils {

  public TranscodeJobsUtils() {
    super(new TranscodeJobs());
    this.gson =
        new GsonBuilder()
            .addDeserializationExclusionStrategy(
                new ExclusionStrategy() {
                  @Override
                  public boolean shouldSkipField(FieldAttributes f) {
                    return f.getAnnotation(SkipDeserialisation.class) != null;
                  }

                  @Override
                  public boolean shouldSkipClass(Class<?> clazz) {
                    return false;
                  }
                })
            .setPrettyPrinting()
            .create();
  }

  public TranscodeJobs getOldestJobWithLibVersion() {
    return (TranscodeJobs)
        genericCollection
            .find()
            .filter(Filters.ne("libVersion", null))
            .sort(new BasicDBObject("createdAt", 1))
            .first();
  }

  public TranscodeJobs getJobWithFragments() {
    Bson query =
        Filters.elemMatch(
            "transcodes", Filters.and(Filters.exists("fragments"), Filters.ne("fragments", null)));

    return (TranscodeJobs)
        genericCollection.find().filter(query).sort(new BasicDBObject("updatedAt", 1)).first();
  }

  public TranscodeJobs setTranscodes(
      tv.pluto.ip.dal.transcodejobs.TranscodeJobs.TranscodeJob grpcUpdatedJob,
      TranscodeJobs grpcResponseTranscodeJob) {
    List<Transcode> transcodes = new ArrayList<>();

    grpcUpdatedJob
        .getTranscodesList()
        .forEach(
            transcode -> {
              Fragments grpcFragments =
                  Fragments.builder()
                      .breakpoints(transcode.getFragments().getBreakpointsList())
                      .subClips(new TreeMap<>(transcode.getFragments().getSubClipsMap()))
                      .build();

              Transcode transcodeMongo = this.mapGrpcObjectToPojo(transcode, Transcode.class);

              if (grpcFragments.getBreakpoints().isEmpty()
                  && grpcFragments.getSubClips().isEmpty()) {
                transcodeMongo.setFragments(null);
              } else {
                transcodeMongo.setFragments(grpcFragments);
              }

              transcodes.add(transcodeMongo);
            });

    grpcResponseTranscodeJob.setTranscodes(transcodes);

    return grpcResponseTranscodeJob;
  }
}
