#include "protection.h"
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"

int av_protection_check_side_data(AVProtectionSession *protection, struct AVPacket *pkt, int *error){
  int i, j;
  int ret = 0, res;
  AVProtectionInfo* *infos = NULL;
  AVProtectionInfo *info;
  int n_infos = 0;
   av_log(NULL, AV_LOG_DEBUG, "av_protection_check_side_data: checking side data of packet %"PRId64", %d\n", pkt->dts, pkt->side_data_elems);
  for (i = 0; i < pkt->side_data_elems; i++){
    av_log(NULL, AV_LOG_DEBUG, "av_protection_check_side_data: checking one side data of packet\n");
    if (pkt->side_data[i].type == AV_PKT_DATA_NEW_PSSH){
      info = av_mallocz(sizeof(AVProtectionInfo));
      info->size = pkt->side_data[i].size;
      info->info = av_malloc(info->size);
      av_log(NULL, AV_LOG_DEBUG, "av_protection_check_side_data: found PSSH\n");
      if (!info){
        av_free(info);
        ret = AVERROR(ENOMEM);
        goto fail;
      }
      memcpy(info->info, pkt->side_data[i].data, info->size);
      for (j = 0; j < n_infos; j++){
        if (infos[j]->size == info->size && !memcmp(infos[j]->info, info->info, info->size)){
          av_free(info->info);
          av_free(info);
          break;
        }
      }
      if (j == n_infos){
        av_dynarray_add_nofree(&infos, &n_infos, info);
      }
    }
  }
  if (infos){
    av_log(NULL, AV_LOG_DEBUG, "av_protection_check_side_data: will call add_protection_info\n");
    res = protection->protection->add_protection_info(protection, infos, n_infos, error);
    if (res == 0){
      ret++;
    }
  }
fail:
  if (ret < 0){
    av_log(NULL, AV_LOG_ERROR, "av_protection_check_side_data: error %d\n", ret);
  }
  for (i = 0; i < n_infos; i++){
    av_free(infos[i]->info);
    av_free(infos[i]);
  }
  if (infos){
    av_free(infos);
    if (ret == 0){
      ret = -1;
    }
  }
  return ret;
}

int av_protection_decrypt_packet(AVProtectionSession* protection, AVCodecContext* ctx, AVPacket* pkt)
{
  int ret = 0;
  if (!protection){
    return AVERROR_INVALIDDATA;
  }
  if (!ctx->handles_protection && pkt->algo_id == 1){
    //we should decrypt packet here, the codec doesn't handle DRM
//     av_log(NULL,AV_LOG_DEBUG, "will decrypt packet with dts %"PRId64" for stream %d\n", pkt->dts, pkt->stream_index);
    ret = protection->protection->decrypt_packet(protection, pkt->data, pkt->size, pkt->KID, pkt->IV, pkt->IV_size, pkt->clear, pkt->encrypted, pkt->nb_subsamples);
  }
  
fail:
  if (ret != 0){
    av_log(NULL, AV_LOG_ERROR, "av_protection_decrypt_packet: could not decrypt packet, error %d\n", ret);
  }
  return ret;
}
