text: /**
   * This module adds [DFP support]{@link https://www.doubleclickbygoogle.com/} for Video to Prebid.
   */
  
  import { registerVideoSupport } from '../src/adServerManager.js';
  import { targeting } from '../src/targeting.js';
  import { deepAccess, isEmpty, logError, parseSizesInput, formatQS, parseUrl, buildUrl } from '../src/utils.js';
  import { config } from '../src/config.js';
  import { getHook, submodule } from '../src/hook.js';
  import { auctionManager } from '../src/auctionManager.js';
  
  /**
   * @typedef {Object} DfpVideoParams
   *
   * This object contains the params needed to form a URL which hits the
   * [DFP API]{@link https://support.google.com/dfp_premium/answer/1068325?hl=en}.
   *
   * All params (except iu, mentioned below) should be considered optional. This module will choose reasonable
   * defaults for all of the other required params.
   *
   * The cust_params property, if present, must be an object. It will be merged with the rest of the
   * standard Prebid targeting params (hb_adid, hb_bidder, etc).
   *
   * @param {string} iu This param *must* be included, in order for us to create a valid request.
   * @param [string] description_url This field is required if you want Ad Exchange to bid on our ad unit...
   *   but otherwise optional
   */
  
  /**
   * @typedef {Object} DfpVideoOptions
   *
   * @param {Object} adUnit The adUnit which this bid is supposed to help fill.
   * @param [Object] bid The bid which should be considered alongside the rest of the adserver's demand.
   *   If this isn't defined, then we'll use the winning bid for the adUnit.
   *
   * @param {DfpVideoParams} [params] Query params which should be set on the DFP request.
   *   These will override this module's defaults whenever they conflict.
   * @param {string} [url] video adserver url
   */
  
  /** Safe defaults which work on pretty much all video calls. */
  const defaultParamConstants = {
    env: 'vp',
    gdfp_req: 1,
    output: 'xml_vast3',
    unviewed_position_start: 1,
  };
  
  export const adpodUtils = {};
  
  /**
   * Merge all the bid data and publisher-supplied options into a single URL, and then return it.
   *
   * @see [The DFP API]{@link https://support.google.com/dfp_premium/answer/1068325?hl=en#env} for details.
   *
   * @param {DfpVideoOptions} options Options which should be used to construct the URL.
   *
   * @return {string} A URL which calls DFP, letting options.bid
   *   (or the auction's winning bid for this adUnit, if undefined) compete alongside the rest of the
   *   demand in DFP.
   */
  export function buildDfpVideoUrl(options) {
    if (!options.params && !options.url) {
      logError(`A params object or a url is required to use $$PREBID_GLOBAL$$.adServers.dfp.buildVideoUrl`);
      return;
    }
  
    const adUnit = options.adUnit;
    const bid = options.bid || targeting.getWinningBids(adUnit.code)[0];
  
    let urlComponents = {};
  
    if (options.url) {
      // when both `url` and `params` are given, parsed url will be overwriten
      // with any matching param components
      urlComponents = parseUrl(options.url, {noDecodeWholeURL: true});
  
      if (isEmpty(options.params)) {
        return buildUrlFromAdserverUrlComponents(urlComponents, bid, options);
      }
    }
  
    const derivedParams = {
      correlator: Date.now(),
      sz: parseSizesInput(adUnit.sizes).join('|'),
      url: encodeURIComponent(location.href),
    };
    const encodedCustomParams = getCustParams(bid, options);
  
    const queryParams = Object.assign({},
      defaultParamConstants,
      urlComponents.search,
      derivedParams,
      options.params,
      { cust_params: encodedCustomParams }
    );
  
    const descriptionUrl = getDescriptionUrl(bid, options, 'params');
    if (descriptionUrl) { queryParams.description_url = descriptionUrl; }
  
    return buildUrl({
      protocol: 'https',
      host: 'securepubads.g.doubleclick.net',
      pathname: '/gampad/ads',
      search: queryParams
    });
  }
  
  export function notifyTranslationModule(fn) {
    fn.call(this, 'dfp');
  }
  
  getHook('registerAdserver').before(notifyTranslationModule);
  
  /**
   * @typedef {Object} DfpAdpodOptions
   *
   * @param {string} code Ad Unit code
   * @param {Object} params Query params which should be set on the DFP request.
   * These will override this module's defaults whenever they conflict.
   * @param {function} callback Callback function to execute when master tag is ready
   */
  
  /**
   * Creates master tag url for long-form
   * @param {DfpAdpodOptions} options
   * @returns {string} A URL which calls DFP with custom adpod targeting key values to compete with rest of the demand in DFP
   */
  export function buildAdpodVideoUrl({code, params, callback} = {}) {
    if (!params || !callback) {
      logError(`A params object and a callback is required to use pbjs.adServers.dfp.buildAdpodVideoUrl`);
      return;
    }
  
    const derivedParams = {
      correlator: Date.now(),
      sz: getSizeForAdUnit(code),
      url: encodeURIComponent(location.href),
    };
  
    function getSizeForAdUnit(code) {
      let adUnit = auctionManager.getAdUnits()
        .filter((adUnit) => adUnit.code === code)
      let sizes = deepAccess(adUnit[0], 'mediaTypes.video.playerSize');
      return parseSizesInput(sizes).join('|');
    }
  
    adpodUtils.getTargeting({
      'codes': [code],
      'callback': createMasterTag
    });
  
    function createMasterTag(err, targeting) {
      if (err) {
        callback(err, null);
        return;
      }
  
      let initialValue = {
        [adpodUtils.TARGETING_KEY_PB_CAT_DUR]: undefined,
        [adpodUtils.TARGETING_KEY_CACHE_ID]: undefined
      }
      let customParams = {};
      if (targeting[code]) {
        customParams = targeting[code].reduce((acc, curValue) => {
          if (Object.keys(curValue)[0] === adpodUtils.TARGETING_KEY_PB_CAT_DUR) {
            acc[adpodUtils.TARGETING_KEY_PB_CAT_DUR] = (typeof acc[adpodUtils.TARGETING_KEY_PB_CAT_DUR] !== 'undefined') ? acc[adpodUtils.TARGETING_KEY_PB_CAT_DUR] + ',' + curValue[adpodUtils.TARGETING_KEY_PB_CAT_DUR] : curValue[adpodUtils.TARGETING_KEY_PB_CAT_DUR];
          } else if (Object.keys(curValue)[0] === adpodUtils.TARGETING_KEY_CACHE_ID) {
            acc[adpodUtils.TARGETING_KEY_CACHE_ID] = curValue[adpodUtils.TARGETING_KEY_CACHE_ID]
          }
          return acc;
        }, initialValue);
      }
  
      let encodedCustomParams = encodeURIComponent(formatQS(customParams));
  
      const queryParams = Object.assign({},
        defaultParamConstants,
        derivedParams,
        params,
        { cust_params: encodedCustomParams }
      );
  
      const masterTag = buildUrl({
        protocol: 'https',
        host: 'securepubads.g.doubleclick.net',
        pathname: '/gampad/ads',
        search: queryParams
      });
  
      callback(null, masterTag);
    }
  }
  
  /**
   * Builds a video url from a base dfp video url and a winning bid, appending
   * Prebid-specific key-values.
   * @param {Object} components base video adserver url parsed into components object
   * @param {AdapterBidResponse} bid winning bid object to append parameters from
   * @param {Object} options Options which should be used to construct the URL (used for custom params).
   * @return {string} video url
   */
  function buildUrlFromAdserverUrlComponents(components, bid, options) {
    const descriptionUrl = getDescriptionUrl(bid, components, 'search');
    if (descriptionUrl) { components.search.description_url = descriptionUrl; }
  
    const encodedCustomParams = getCustParams(bid, options);
    components.search.cust_params = (components.search.cust_params) ? components.search.cust_params + '%26' + encodedCustomParams : encodedCustomParams;
  
    return buildUrl(components);
  }
  
  /**
   * Returns the encoded vast url if it exists on a bid object, only if prebid-cache
   * is disabled, and description_url is not already set on a given input
   * @param {AdapterBidResponse} bid object to check for vast url
   * @param {Object} components the object to check that description_url is NOT set on
   * @param {string} prop the property of components that would contain description_url
   * @return {string | undefined} The encoded vast url if it exists, or undefined
   */
  function getDescriptionUrl(bid, components, prop) {
    if (config.getConfig('cache.url')) { return; }
  
    if (!deepAccess(components, `${prop}.description_url`)) {
      const vastUrl = bid && bid.vastUrl;
      if (vastUrl) { return encodeURIComponent(vastUrl); }
    } else {
      logError(`input cannnot contain description_url`);
    }
  }
  
  /**
   * Returns the encoded `cust_params` from the bid.adserverTargeting and adds the `hb_uuid`, and `hb_cache_id`. Optionally the options.params.cust_params
   * @param {AdapterBidResponse} bid
   * @param {Object} options this is the options passed in from the `buildDfpVideoUrl` function
   * @return {Object} Encoded key value pairs for cust_params
   */
  function getCustParams(bid, options) {
    const adserverTargeting = (bid && bid.adserverTargeting) || {};
  
    let allTargetingData = {};
    const adUnit = options && options.adUnit;
    if (adUnit) {
      let allTargeting = targeting.getAllTargeting(adUnit.code);
      allTargetingData = (allTargeting) ? allTargeting[adUnit.code] : {};
    }
  
    const optCustParams = deepAccess(options, 'params.cust_params');
    let customParams = Object.assign({},
      // Why are we adding standard keys here ? Refer https://github.com/prebid/Prebid.js/issues/3664
      { hb_uuid: bid && bid.videoCacheKey },
      // hb_uuid will be deprecated and replaced by hb_cache_id
      { hb_cache_id: bid && bid.videoCacheKey },
      allTargetingData,
      adserverTargeting,
      optCustParams,
    );
    // TODO : Remove below function and change the constant value in file to update the key names for video
    // Changing few key name might have impact on banner as well as we ignore few key names , hence using below function
    // to get the cust_params that should be attached to dfp.
    // It will also handle the send allBids cases
    if (window.PWT && window.PWT.getCustomParamsForDFPVideo) {
      customParams = window.PWT.getCustomParamsForDFPVideo(optCustParams, bid);
    }
    return encodeURIComponent(formatQS(customParams));
  }
  
  registerVideoSupport('dfp', {
    buildVideoUrl: buildDfpVideoUrl,
    buildAdpodVideoUrl: buildAdpodVideoUrl,
    getAdpodTargeting: (args) => adpodUtils.getTargeting(args)
  });
  
  submodule('adpod', adpodUtils);
  