"use strict";var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");var _freeze = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/freeze")); /**
 * Copyright (c) 2015-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file at
 * https://github.com/facebook/create-react-app/blob/master/LICENSE
 */

const open = require('open');
const execa = require('execa');
const chalk = require('chalk');
const execSync = require('child_process').execSync;
const chromeLauncher = require('chrome-simple-launcher');
const puppeteer = require('puppeteer');
const lookupChromeWindows = require('./sniffer-windows').default;

// https://github.com/sindresorhus/open#app
const OSX_CHROME = 'google chrome';

const Actions = (0, _freeze.default)({
  NONE: 0,
  BROWSER: 1,
  SCRIPT: 2
});

function getBrowserEnv() {
  // Attempt to honor this environment variable.
  // It is specific to the operating system.
  // See https://github.com/sindresorhus/open#app for documentation.
  const value = process.env.BROWSER;
  let action;
  if (!value) {
    // Default.
    action = Actions.BROWSER;
  } else if (value.toLowerCase().endsWith('.js')) {
    action = Actions.SCRIPT;
  } else if (value.toLowerCase() === 'none') {
    action = Actions.NONE;
  } else {
    action = Actions.BROWSER;
  }
  return { action, value };
}

function executeNodeScript(scriptPath, url) {
  const extraArgs = process.argv.slice(2);
  const child = execa('node', [scriptPath, ...extraArgs, url], {
    stdio: 'inherit'
  });
  child.on('close', (code) => {
    if (code !== 0) {
      console.log();
      console.log(
        chalk.red(
          'The script specified as BROWSER environment variable failed.'
        )
      );
      console.log(chalk.cyan(scriptPath) + ' exited with code ' + code + '.');
      console.log();
    }
  });
  return true;
}

let browserDev;
let chromePath;
async function startBrowserProcess(browser, url) {
  // If we're on OS X, the user hasn't specifically
  // requested a different browser, we can try opening
  // Chrome with AppleScript. This lets us reuse an
  // existing tab when possible instead of creating a new one.
  const shouldTryOpenChromeWithAppleScript =
  process.platform === 'darwin' && (
  typeof browser !== 'string' || browser === OSX_CHROME);

  if (shouldTryOpenChromeWithAppleScript) {
    try {
      // Try our best to reuse existing tab
      // on OS X Google Chrome with AppleScript
      execSync('ps cax | grep "Google Chrome"');
      execSync('osascript openChrome.applescript "' + encodeURI(url) + '"', {
        cwd: __dirname,
        stdio: 'ignore'
      });
      return true;
    } catch (err) {

      // Ignore errors.
    }}

  // Another special case: on OS X, check if BROWSER has been set to "open".
  // In this case, instead of passing the string `open` to `open` function (which won't work),
  // just ignore it (thus ensuring the intended behavior, i.e. opening the system browser):
  // https://github.com/facebook/create-react-app/pull/1690#issuecomment-283518768
  if (process.platform === 'darwin' && browser === 'open') {
    browser = undefined;
  }

  // Fallback to open
  // (It will always open new tab)
  try {
    try {
      if (browserDev) {
        const pages = await browserDev.pages();
        if (pages && pages.length > 0) {
          for (const page of pages) {
            // 检查页面是否已关闭
            if (await page.isClosed()) continue;

            // 获取页面的当前 URL
            const currentUrl = await page.url();

            // 检查当前 URL 是否与目标 URL 匹配
            if (currentUrl === url) {
              console.info('刷新当前已存在的调试页面：' + url);

              // 刷新当前页面
              await page.reload();

              // 将浏览器窗口拉到前台
              await page.bringToFront();

              return true;
            }
          }

          const page = await browserDev.newPage();
          await page.goto(url); // 打开网页
          await page.bringToFront(); // 将浏览器窗口拉到前台
          return true;
        }
      }

      // 强制关闭浏览器窗口
      if (browserDev) {
        await browserDev.close();
      }

      if (!chromePath) {
        chromePath = await lookupChromeWindows();
      }

      browserDev = await puppeteer.launch({
        executablePath: chromePath, // Specify the path here
        headless: false,
        defaultViewport: null,
        ignoreDefaultArgs: ['--enable-automation', '--enable-blink-features=IdleDetection'],
        args: ['--start-maximized', '--no-default-browser-check']
      });
      const pages = await browserDev.pages();
      const page = pages[0];
      await page.goto(url); // 打开网页
      await page.bringToFront(); // 将浏览器窗口拉到前台
    } catch (e) {
      const error = () => {
        var options = { app: browser, url: true };
        open(url, options).catch(() => {}); // Prevent `unhandledRejection` error.
      };
      chromeLauncher.launch(url, {
        onError: error
      }).catch(() => {
        var options = { app: browser, url: true };
        open(url, options).catch(() => {}); // Prevent `unhandledRejection` error.
      });
    }
  } catch (err) {
    return false;
  }
}

/**
 * Reads the BROWSER environment variable and decides what to do with it. Returns
 * true if it opened a browser or ran a node.js script, otherwise false.
 */
exports.openBrowser = function (url) {
  const { action, value } = getBrowserEnv();
  switch (action) {
    case Actions.NONE:
      // Special case: BROWSER="none" will prevent opening completely.
      return false;
    case Actions.SCRIPT:
      return executeNodeScript(value, url);
    case Actions.BROWSER:
      return startBrowserProcess(value, url);
    default:
      throw new Error('Not implemented.');
  }
};