/*
 * (c) 2020 Pluto Inc.
 */
package tv.pluto.mongo.utils;

import static com.mongodb.client.model.Projections.fields;
import static com.mongodb.client.model.Projections.include;

import com.mongodb.BasicDBObject;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.bson.conversions.Bson;
import org.bson.types.ObjectId;
import tv.pluto.mongo.entities.vod.VodCategories;

public class VodUtils extends MongoUtils {

  public VodUtils() {
    this.genericCollection = this.collectionVodCategories;
    this.setContentFeedsDates();
  }

  /**
   * Get random VodCategory
   *
   * @return random VodCategory
   */
  public VodCategories getRandomVodCategory() {
    return getRandomItem(getVodCategoriesList(MongoUtils.LIMIT));
  }

  /**
   * Get limited list of VodCategories
   *
   * @param limit limit for query
   * @return List of VodCategories
   */
  public List<VodCategories> getVodCategoriesList(int limit) {
    List<VodCategories> result = new ArrayList<>();
    collectionVodCategories.find().limit(limit).forEach(result::add);
    return result;
  }

  /**
   * Get ids of active vod categories for specific region
   *
   * @param activeRegion active region id
   * @return list of ids
   */
  public List<String> getActiveVodCategoryIds(String activeRegion) {
    BasicDBObject vodCategoryQuery = new BasicDBObject();
    vodCategoryQuery.put("activeRegion", activeRegion.toLowerCase());
    vodCategoryQuery.append("enabled", true);

    List<String> vodCategoryIds = new ArrayList<>();
    collectionVodCategories
        .find(vodCategoryQuery)
        .forEach(category -> vodCategoryIds.add(category.getId()));

    return vodCategoryIds;
  }

  /**
   * Get active episode ids
   *
   * @param vodCategoryId id of vod category
   * @return list of episode ids
   */
  public List<String> getActiveEpisodeIdsForCategoryId(String vodCategoryId) {
    BasicDBObject vodCategoryEntriesQuery = new BasicDBObject();
    vodCategoryEntriesQuery.put("vodCategory", new ObjectId(vodCategoryId));

    // Get ids of episodes from VodCategoryEntries collection if exists
    List<ObjectId> vodEpisodesIds = new ArrayList<>();
    collectionVodCategoryEntries
        .find(vodCategoryEntriesQuery)
        .forEach(
            vodCategoryEntry -> {
              if (!vodCategoryEntry.getEpisode().isEmpty()) {
                vodEpisodesIds.add(new ObjectId(vodCategoryEntry.getEpisode()));
              }
            });

    // Get ids of series from VodCategoryEntries collection if exists
    List<ObjectId> vodSeriesIds = new ArrayList<>();
    collectionVodCategoryEntries
        .find(vodCategoryEntriesQuery)
        .forEach(
            vodCategoryEntry -> {
              if (!vodCategoryEntry.getSeries().isEmpty()) {
                vodSeriesIds.add(new ObjectId(vodCategoryEntry.getSeries()));
              }
            });

    List<BasicDBObject> mongoOrList = new ArrayList<>();

    // Check if VodCategoryEntries has episode
    if (!vodEpisodesIds.isEmpty()) {
      mongoOrList.add(new BasicDBObject("_id", new BasicDBObject("$in", vodEpisodesIds)));
    }

    // Check if VodCategoryEntries has series
    if (!vodSeriesIds.isEmpty()) {
      mongoOrList.add(new BasicDBObject("series", new BasicDBObject("$in", vodSeriesIds)));
    }

    BasicDBObject query =
        new BasicDBObject("distributeAs.AVOD", true)
            .append("content.0", new BasicDBObject("$exists", true));

    // If series or episode exists add them to the or query
    if (!mongoOrList.isEmpty()) {
      query = query.append("$or", mongoOrList);
    }

    List<String> episodesIds = new ArrayList<>();
    collectionEpisodes
        .find(query)
        .projection(fields(include("_id")))
        .forEach(episode -> episodesIds.add(episode.getId()));

    return episodesIds;
  }

  public List<VodCategories> getByIds(List<String> ids, Bson sort) {
    List<VodCategories> result = new ArrayList<>();

    BasicDBObject query = new BasicDBObject();
    query.put("_id", new BasicDBObject("$in", transformStringsToIds(ids)));

    genericCollection.find(query).sort(sort).forEach(e -> result.add((VodCategories) e));

    return result;
  }

  /**
   * Get list of random Vod Categories ids
   *
   * @return list of ids
   */
  public List<String> getRandomVodCategoriesIds() {
    return getDocuments(MongoUtils.LIMIT).stream()
        .map(vodCategory -> ((VodCategories) vodCategory).getId())
        .collect(Collectors.toList());
  }
}
