"use strict";

const path = require('path');

const fs = require('fs');

const http = require('http');

const WebSocket = require('ws');

const sirv = require('sirv');

const _ = require('lodash');

const {
  bold
} = require('chalk');

const Logger = require('./Logger');

const analyzer = require('./analyzer');

const {
  open
} = require('./utils');

const {
  renderViewer
} = require('./template');

const projectRoot = path.resolve(__dirname, '..');

function resolveTitle(reportTitle) {
  if (typeof reportTitle === 'function') {
    return reportTitle();
  } else {
    return reportTitle;
  }
}

module.exports = {
  startServer,
  generateReport,
  generateJSONReport,
  // deprecated
  start: startServer
};

async function startServer(bundleStats, opts) {
  const {
    port = 8888,
    host = '127.0.0.1',
    openBrowser = true,
    bundleDir = null,
    logger = new Logger(),
    defaultSizes = 'parsed',
    excludeAssets = null,
    reportTitle
  } = opts || {};
  const analyzerOpts = {
    logger,
    excludeAssets
  };
  let chartData = getChartData(analyzerOpts, bundleStats, bundleDir);
  if (!chartData) return;
  const sirvMiddleware = sirv(`${projectRoot}/public`, {
    // disables caching and traverse the file system on every request
    dev: true
  });
  const server = http.createServer((req, res) => {
    if (req.method === 'GET' && req.url === '/') {
      const html = renderViewer({
        mode: 'server',
        title: resolveTitle(reportTitle),
        chartData,
        defaultSizes,
        enableWebSocket: true
      });
      res.writeHead(200, {
        'Content-Type': 'text/html'
      });
      res.end(html);
    } else {
      sirvMiddleware(req, res);
    }
  });
  await new Promise(resolve => {
    server.listen(port, host, () => {
      resolve();
      const url = `http://${host}:${server.address().port}`;
      logger.info(`${bold('Webpack Bundle Analyzer')} is started at ${bold(url)}\n` + `Use ${bold('Ctrl+C')} to close it`);

      if (openBrowser) {
        open(url, logger);
      }
    });
  });
  const wss = new WebSocket.Server({
    server
  });
  wss.on('connection', ws => {
    ws.on('error', err => {
      // Ignore network errors like `ECONNRESET`, `EPIPE`, etc.
      if (err.errno) return;
      logger.info(err.message);
    });
  });
  return {
    ws: wss,
    http: server,
    updateChartData
  };

  function updateChartData(bundleStats) {
    const newChartData = getChartData(analyzerOpts, bundleStats, bundleDir);
    if (!newChartData) return;
    chartData = newChartData;
    wss.clients.forEach(client => {
      if (client.readyState === WebSocket.OPEN) {
        client.send(JSON.stringify({
          event: 'chartDataUpdated',
          data: newChartData
        }));
      }
    });
  }
}

async function generateReport(bundleStats, opts) {
  const {
    openBrowser = true,
    reportFilename,
    reportTitle,
    bundleDir = null,
    logger = new Logger(),
    defaultSizes = 'parsed',
    excludeAssets = null
  } = opts || {};
  const chartData = getChartData({
    logger,
    excludeAssets
  }, bundleStats, bundleDir);
  if (!chartData) return;
  const reportHtml = renderViewer({
    mode: 'static',
    title: resolveTitle(reportTitle),
    chartData,
    defaultSizes,
    enableWebSocket: false
  });
  const reportFilepath = path.resolve(bundleDir || process.cwd(), reportFilename);
  fs.mkdirSync(path.dirname(reportFilepath), {
    recursive: true
  });
  fs.writeFileSync(reportFilepath, reportHtml);
  logger.info(`${bold('Webpack Bundle Analyzer')} saved report to ${bold(reportFilepath)}`);

  if (openBrowser) {
    open(`file://${reportFilepath}`, logger);
  }
}

async function generateJSONReport(bundleStats, opts) {
  const {
    reportFilename,
    bundleDir = null,
    logger = new Logger(),
    excludeAssets = null
  } = opts || {};
  const chartData = getChartData({
    logger,
    excludeAssets
  }, bundleStats, bundleDir);
  if (!chartData) return;
  await fs.promises.mkdir(path.dirname(reportFilename), {
    recursive: true
  });
  await fs.promises.writeFile(reportFilename, JSON.stringify(chartData));
  logger.info(`${bold('Webpack Bundle Analyzer')} saved JSON report to ${bold(reportFilename)}`);
}

function getChartData(analyzerOpts, ...args) {
  let chartData;
  const {
    logger
  } = analyzerOpts;

  try {
    chartData = analyzer.getViewerData(...args, analyzerOpts);
  } catch (err) {
    logger.error(`Could't analyze webpack bundle:\n${err}`);
    logger.debug(err.stack);
    chartData = null;
  }

  if (_.isPlainObject(chartData) && _.isEmpty(chartData)) {
    logger.error("Could't find any javascript bundles in provided stats file");
    chartData = null;
  }

  return chartData;
}