/*
 * (c) 2020 Pluto Inc.
 */
package tv.pluto.grpc.series;

import static tv.pluto.ip.dal.series.SeriesOuterClass.CreateRequest;
import static tv.pluto.ip.dal.series.SeriesOuterClass.GetByIdRequest;
import static tv.pluto.ip.dal.series.SeriesOuterClass.GetByIdResponse;
import static tv.pluto.ip.dal.series.SeriesOuterClass.GetByIdsRequest;
import static tv.pluto.ip.dal.series.SeriesOuterClass.GetByIdsResponse;
import static tv.pluto.ip.dal.series.SeriesOuterClass.GetDocumentsUpdatedBetweenDatesRequest;
import static tv.pluto.ip.dal.series.SeriesOuterClass.UpdateContentMamUniqueIdsByIdsRequest;
import static tv.pluto.ip.dal.series.SeriesOuterClass.UpdateContentMamUniqueIdsByIdsResponse;
import static tv.pluto.ip.dal.series.SeriesOuterClass.UpdateFieldsRequest;

import com.plutotv.test.lib.LogUtils;
import io.grpc.Channel;
import java.util.List;
import java.util.logging.Logger;
import tv.pluto.grpc.GenericGrpcClient;
import tv.pluto.ip.dal.series.SeriesManagerGrpc;
import tv.pluto.ip.dal.series.SeriesOuterClass;
import tv.pluto.mongo.entities.common.ObjectIdContentIdSet;

/** Class represents gRPC client for <b>series.proto</b> file */
public class SeriesClient extends GenericGrpcClient {
  private static final Logger logger = Logger.getLogger(SeriesClient.class.getName());
  private SeriesManagerGrpc.SeriesManagerBlockingStub blockingStub;
  private SeriesOuterClass.GetAllPagedRequest.Builder getAllPagedBuilder =
      SeriesOuterClass.GetAllPagedRequest.newBuilder();

  public SeriesClient(Channel channel, boolean auth) {
    blockingStub = SeriesManagerGrpc.newBlockingStub(channel);

    if (auth) blockingStub = blockingStub.withInterceptors(CLIENT_INTERCEPTOR_AUTH);
    else blockingStub = blockingStub.withInterceptors(CLIENT_INTERCEPTOR);

    this.getDocumentsUpdatedBetweenDatesRequestBuilder =
        GetDocumentsUpdatedBetweenDatesRequest.newBuilder();

    this.getCFeedsAllIdsBuilder = SeriesOuterClass.CFeedsSyncAllIdsRequest.newBuilder();
    this.getCFeedsSyncDocumentsBuilder = SeriesOuterClass.CFeedsSyncDocumentsRequest.newBuilder();
  }

  /**
   * Method represents gRPC method GetSeriesById from <b>series.proto</b> file
   *
   * @param seriesId series id
   * @return GetSeriesByIdResponse object
   */
  public GetByIdResponse getSeriesById(String seriesId) {
    logger.info("Getting info for series with id: " + seriesId + " ...");
    GetByIdRequest request = GetByIdRequest.newBuilder().setId(seriesId).build();

    return blockingStub.getById(request);
  }

  public GetByIdsResponse getSeriesByIds(GetByIdsRequest request) {
    return blockingStub.getByIds(request);
  }

  public UpdateContentMamUniqueIdsByIdsResponse updateContentMamUniqueIdsByIds(
      List<ObjectIdContentIdSet> objectIdContentIdSets) {
    LogUtils.logInfoMessage("Updating series contentUUID for " + objectIdContentIdSets);

    UpdateContentMamUniqueIdsByIdsRequest.Builder builder =
        UpdateContentMamUniqueIdsByIdsRequest.newBuilder();

    objectIdContentIdSets.forEach(
        value ->
            builder.addObjectIdContentIdSets(
                SeriesOuterClass.ObjectIdContentIdSet.newBuilder()
                    .setId(value.getId())
                    .setContentUUID(value.getContentUUID())
                    .build()));

    return blockingStub.updateContentMamUniqueIdsByIds(builder.build());
  }

  public SeriesOuterClass.UpdateFieldsResponse getUpdateFields(
      String id, SeriesOuterClass.Series seriesDoc, Iterable<String> updatedFields) {
    UpdateFieldsRequest updateFieldsRequest =
        UpdateFieldsRequest.newBuilder()
            .setId(id)
            .setDocument(seriesDoc)
            .addAllUpdateFields(updatedFields)
            .build();

    return blockingStub.updateFields(updateFieldsRequest);
  }

  public SeriesOuterClass.CreateResponse createSeries(SeriesOuterClass.Series series) {
    CreateRequest createRequest = CreateRequest.newBuilder().setDocument(series).build();
    return blockingStub.create(createRequest);
  }

  public SeriesOuterClass.DeleteByIdResponse deleteById(String id) {
    SeriesOuterClass.DeleteByIdRequest request =
        SeriesOuterClass.DeleteByIdRequest.newBuilder().setId(id).build();
    return blockingStub.deleteById(request);
  }

  public SeriesOuterClass.GetPopulatedSeriesByIdResponse getPopulatedSeriesById(
      String id, SeriesOuterClass.PopulatePath.Builder path) {
    SeriesOuterClass.GetPopulatedSeriesByIdRequest.Builder builder =
        SeriesOuterClass.GetPopulatedSeriesByIdRequest.newBuilder().setId(id);
    if (path != null) builder.addPopulate(path);

    return blockingStub.getPopulatedSeriesById(builder.build());
  }

  public SeriesOuterClass.GetSeriesUsingExternalIdResponse getSeriesUsingExternalId(
      tv.pluto.ip.dal.series.SeriesOuterClass.GetSeriesUsingExternalIdRequest request) {
    return blockingStub.getSeriesUsingExternalId(request);
  }

  public SeriesOuterClass.GetSeriesPartnerByIdsResponse getSeriesPartnerByIds(
      List<String> listSeriesIds) {
    SeriesOuterClass.GetSeriesPartnerByIdsRequest request =
        SeriesOuterClass.GetSeriesPartnerByIdsRequest.newBuilder().addAllIds(listSeriesIds).build();
    return blockingStub.getSeriesPartnerByIds(request);
  }

  public SeriesOuterClass.Filter seriesFilter(
      String field, String value, String type, String operator) {
    SeriesOuterClass.Filter.Builder builder = SeriesOuterClass.Filter.newBuilder();
    if (field != null) builder.setField(field);
    if (value != null) builder.setValue(value);
    if (type != null) builder.setType(type);
    if (operator != null) builder.setOperator(operator);

    return builder.build();
  }

  public SeriesOuterClass.GetAllPagedResponse getAllPagedNoException(
      int limit,
      int offset,
      List<SeriesOuterClass.GetAllPagedSort> sort,
      List<SeriesOuterClass.Filter> listFilters,
      Boolean count) {
    SeriesOuterClass.GetAllPagedRequest.Builder builder =
        SeriesOuterClass.GetAllPagedRequest.newBuilder().setLimit(limit).setOffset(offset);
    if (sort != null) builder.addAllSort(sort);
    if (listFilters != null) builder.addAllFilters(listFilters);
    if (count != null) builder.setDisableTotalCount(count);

    return blockingStub.getAllPaged(builder.build());
  }

  public SeriesOuterClass.GetSeriesByNameAndActiveRegionAndCustomReferenceResponse
      getSeriesByNameAndActiveRegionAndCustomReferences(
          tv.pluto.ip.dal.series.SeriesOuterClass
                  .GetSeriesByNameAndActiveRegionAndCustomReferencesRequest
              request) {
    return blockingStub.getSeriesByNameAndActiveRegionAndCustomReferences(request);
  }

  public SeriesOuterClass.GetSeriesByChannelIdResponse getSeriesByChannelIdResponse(
      String channelId) {
    SeriesOuterClass.GetSeriesByChannelIdRequest.Builder builder =
        SeriesOuterClass.GetSeriesByChannelIdRequest.newBuilder().setId(channelId);
    return blockingStub.getSeriesByChannelId(builder.build());
  }

  public SeriesOuterClass.GetSeriesFutureTimelineResponse getSeriesFutureTimelineResponse(
      String seriesID, String channelId) {
    SeriesOuterClass.GetSeriesFutureTimelineRequest.Builder builder =
        SeriesOuterClass.GetSeriesFutureTimelineRequest.newBuilder()
            .setSeriesId(seriesID)
            .setChannelId(channelId);
    return blockingStub.getSeriesFutureTimeline(builder.build());
  }

  public SeriesOuterClass.UpdateRatingsResponse updateRatings(
      String seriesId, String rating, boolean replace) {
    logger.info(
        "Updating ratings for series:  "
            + seriesId
            + " with rating: "
            + rating
            + " and replace: "
            + replace);

    SeriesOuterClass.UpdateRatingsRequest request =
        SeriesOuterClass.UpdateRatingsRequest.newBuilder()
            .setSeriesId(seriesId)
            .setRating(rating)
            .setReplace(replace)
            .build();

    return blockingStub.updateRatings(request);
  }
}
