text: /**
   * Copyright 2015 The AMP HTML Authors. All Rights Reserved.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS-IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  import {startsWith} from './string';
  import {parseQueryString_} from './url-parse-query-string';
  
  /**
   * @typedef {{
   *   localDev: boolean,
   *   development: boolean,
   *   filter: (string|undefined),
   *   minified: boolean,
   *   lite: boolean,
   *   test: boolean,
   *   log: (string|undefined),
   *   version: string,
   *   rtvVersion: string,
   * }}
   */
  export let ModeDef;
  
  /** @type {string} */
  const version = '$internalRuntimeVersion$';
  
  /**
   * `rtvVersion` is the prefixed version we serve off of the cdn.
   * The prefix denotes canary(00) or prod(01) or an experiment version ( > 01).
   * @type {string}
   */
  let rtvVersion = '';
  
  /**
   * A #querySelector query to see if we have any scripts with development paths.
   * @type {string}
   */
  const developmentScriptQuery = 'script[src*="/dist/"],script[src*="/base/"]';
  
  /**
   * Provides info about the current app.
   * @param {?Window=} opt_win
   * @return {!ModeDef}
   */
  export function getMode(opt_win) {
    const win = opt_win || self;
    if (win.AMP_MODE) {
      return win.AMP_MODE;
    }
    return win.AMP_MODE = getMode_(win);
  }
  
  /**
   * Provides info about the current app.
   * @param {!Window} win
   * @return {!ModeDef}
   */
  function getMode_(win) {
    // Magic constants that are replaced by closure compiler.
    // IS_MINIFIED is always replaced with true when closure compiler is used
    // while IS_DEV is only replaced when the --fortesting flag is NOT used.
    const IS_DEV = true;
    const IS_MINIFIED = false;
    const FORCE_LOCALDEV = !!(self.AMP_CONFIG && self.AMP_CONFIG.localDev);
    const AMP_CONFIG_3P_FRAME_HOST = self.AMP_CONFIG &&
        self.AMP_CONFIG.thirdPartyFrameHost;
  
    const isLocalDev = IS_DEV && !!(win.location.hostname == 'localhost' ||
        (FORCE_LOCALDEV && win.location.hostname == AMP_CONFIG_3P_FRAME_HOST) ||
        (win.location.ancestorOrigins && win.location.ancestorOrigins[0] &&
          startsWith(win.location.ancestorOrigins[0], 'http://localhost:'))) &&
        // Filter out localhost running against a prod script.
        // Because all allowed scripts are ours, we know that these can only
        // occur during local dev.
        (!win.document || !!win.document.querySelector(developmentScriptQuery));
  
    const hashQuery = parseQueryString_(
        // location.originalHash is set by the viewer when it removes the fragment
        // from the URL.
        win.location.originalHash || win.location.hash);
  
    const searchQuery = parseQueryString_(win.location.search);
  
    if (!rtvVersion) {
      rtvVersion = getRtvVersion(win, isLocalDev);
    }
  
    // The `minified`, `test` and `localDev` properties are replaced
    // as boolean literals when we run `gulp dist` without the `--fortesting`
    // flags. This improved DCE on the production file we deploy as the code
    // paths for localhost/testing/development are eliminated.
    return {
      localDev: isLocalDev,
      // Triggers validation
      development: !!(hashQuery['development'] == '1' ||
          win.AMP_DEV_MODE),
      examiner: hashQuery['development'] == '2',
      // Allows filtering validation errors by error category. For the
      // available categories, see ErrorCategory in validator/validator.proto.
      filter: hashQuery['filter'],
      minified: IS_MINIFIED,
      // Whether document is in an amp-lite viewer. It signal that the user
      // would prefer to use less bandwidth.
      lite: searchQuery['amp_lite'] != undefined,
      test: IS_DEV && !!(win.AMP_TEST || win.__karma__),
      log: hashQuery['log'],
      version,
      rtvVersion,
    };
  }
  
  /**
   * Retrieve the `rtvVersion` which will have a numeric prefix
   * denoting canary/prod/experiment (unless `isLocalDev` is true).
   *
   * @param {!Window} win
   * @param {boolean} isLocalDev
   * @return {string}
   */
  function getRtvVersion(win, isLocalDev) {
    // If it's local dev then we won't actually have a full version so
    // just use the version.
    if (isLocalDev) {
      return version;
    }
  
    if (win.AMP_CONFIG && win.AMP_CONFIG.v) {
      return win.AMP_CONFIG.v;
    }
  
    // Currently `$internalRuntimeVersion$` and thus `mode.version` contain only
    // major version. The full version however must also carry the minor version.
    // We will default to production default `01` minor version for now.
    // TODO(erwinmombay): decide whether $internalRuntimeVersion$ should contain
    // minor version.
    return `01${version}`;
  }
  
  
  /**
   * @param {!Window} win
   * @param {boolean} isLocalDev
   * @return {string}
   * @visibleForTesting
   */
  export function getRtvVersionForTesting(win, isLocalDev) {
    return getRtvVersion(win, isLocalDev);
  }
  
  
  /** @visibleForTesting */
  export function resetRtvVersionForTesting() {
    rtvVersion = '';
  }
  