"use strict";

var _path = _interopRequireDefault(require("path"));

var _https = _interopRequireDefault(require("https"));

var _webpack = _interopRequireDefault(require("webpack"));

var _express = _interopRequireDefault(require("express"));

var _ws = _interopRequireDefault(require("ws"));

var _compression = _interopRequireDefault(require("compression"));

var _webpackDevMiddleware = _interopRequireDefault(require("webpack-dev-middleware"));

var _httpProxyMiddleware = require("http-proxy-middleware");

var _HMRMiddleware = _interopRequireDefault(require("../middlewares/HMRMiddleware"));

var _utils = require("../utils");

var _httpsOptions = require("./httpsOptions");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

// import fs from 'fs';
const options = (0, _utils.getOptions)();
const httpsOptions = (0, _httpsOptions.httpsOptionsWithUserFriendlyError)(options);
const {
  app: {
    context,
    server
  }
} = options;
const {
  host,
  port,
  domain,
  mode,
  disableContextURL,
  hasMock,
  mockPort
} = server;
const isCompatableHttp2 = Number(process.version.substr(1).split('.')[0]) >= 8;
const contextURL = disableContextURL ? '' : `/${context}`;
const serverUrl = (0, _utils.getServerURL)(server, 'htt' + 'ps');
const {
  writeToDisk
} = options.impactService;
const app = (0, _express.default)();

if (hasMock) {
  app.use(server.mockPrefix, (0, _httpProxyMiddleware.createProxyMiddleware)({
    target: 'ht' + `tp://localhost:${mockPort}`,
    changeOrigin: true
  }));
}

app.use(_express.default.json());
app.use(_express.default.urlencoded({
  extended: true
}));
let config;

if (mode === 'prod') {
  config = require('../configs/webpack.prod.config');
  app.use((0, _compression.default)());
} else if (mode === 'dev' || mode === 'dev-no-warn') {
  config = require('../configs/webpack.dev.config');
} else {
  throw new Error('You must configure valid option in mode');
}

const compiler = (0, _webpack.default)(config);
const webpackServerOptions = {
  logLevel: 'error',
  publicPath: mode === 'prod' ? contextURL === '' ? `${serverUrl}/${contextURL}` : serverUrl + contextURL : config.output.publicPath,
  headers: options.app.enableDevCache ? {
    'Cache-Control': 'public, max-age=604800',
    'Access-Control-Allow-Origin': '*'
  } : {
    'Access-Control-Allow-Origin': '*'
  },
  compress: mode === 'prod'
};

if (options.app.disableWatch) {
  webpackServerOptions.watchOptions = {
    ignored: /./
  };
}

if (writeToDisk) {
  webpackServerOptions.writeToDisk = true;
}

app.use((0, _webpackDevMiddleware.default)(compiler, webpackServerOptions));
app.use((0, _HMRMiddleware.default)(compiler, {
  path: '/sockjs-node/info'
}));
app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', req.get('origin') || '*'); // res.setHeader('Access-Control-Allow-Origin', req.get('origin'));

  res.setHeader('Access-Control-Allow-Private-Network', true);
  res.setHeader('Access-Control-Allow-Credentials', true);
  next();
}).use(`${contextURL}/fonts`, _express.default.static(`${context}/fonts`));
app.options('/*', (req, res) => {
  res.send('Ok');
});
app.use('/wms/*', (req, res) => {
  res.sendFile(_path.default.join(__dirname, '..', '..', 'templates', 'wms', 'index.html'));
});

const httpsServer = _https.default.createServer(httpsOptions, app);

if (httpsOptions) {
  const wss = new _ws.default.Server({
    server: httpsServer
  });
  let wsPool = [];
  wss.on('connection', ws => {
    wsPool.push(ws);
    ws.on('close', () => {
      wsPool = wsPool.filter(ws1 => ws1 !== ws);
    });
    ws.on('message', message => {
      (0, _utils.log)('received: %s', message);
    });
    ws.send('something');
  });
  app.post('/wmsmockapi', (req, res) => {
    wsPool.forEach(ws => {
      const {
        body
      } = req;

      try {
        ws.send(JSON.stringify(body));
      } catch (e) {
        (0, _utils.log)(e, body);
      }
    });
    res.send('success');
  });
}

let webpackCompilation;
let initalHTML;
compiler.hooks.afterCompile.tap('ReactCLI', compilation => {
  webpackCompilation = compilation;
});
compiler.hooks.done.tap('ReactCLI', () => {
  const indexHtml = webpackCompilation.assets['index.html'];

  if (indexHtml) {
    initalHTML = indexHtml.source();
  }
});

if (contextURL) {
  app.use(contextURL, _express.default.static(context));
  app.use(`${contextURL}/*`, (req, res) => {
    res.send(initalHTML);
  });
} else {
  app.use(_express.default.static(context));
  app.use('/*', _express.default.static(context));
}

if (httpsOptions) {
  httpsServer.listen(port, err => {
    if (err) {
      throw err;
    }

    (0, _utils.log)(`Listening at ${serverUrl}${contextURL}/`);
  });

  if (isCompatableHttp2) {
    const http2 = require('http2');

    const http2Server = http2.createSecureServer(httpsOptions); // eslint-disable-next-line no-unused-vars

    http2Server.on('stream', (stream, headers) => {
      stream.respond({
        'content-type': 'text/html',
        ':status': 200
      });
      stream.end('<h1>Hello World! <br>Working with http2</h1>');
    });
    const http2Port = Number(port) + 1;
    http2Server.listen(http2Port, err => {
      if (err) {
        throw err;
      }

      (0, _utils.log)(`Listening at ${(0, _utils.getServerURL)({
        host,
        domain,
        port: http2Port
      }, 'htt' + 'ps')}${contextURL}/`, 'http2 server');
    });
  } else if (httpsOptions) {
    (0, _utils.log)('Your node version didn\'t adopted http2 support. Kindly update that to 8 LTS or above you can engage the http2');
  }
}

const httpPort = Number(port) + (isCompatableHttp2 ? 2 : 1);
app.listen(httpPort, err => {
  if (err) {
    throw err;
  }

  (0, _utils.log)(`Listening at ${(0, _utils.getServerURL)({
    host,
    domain,
    port: port
  }, 'ht' + 'tp')}${contextURL}/`);
});