const nextPort = 5010
const proxyPort = nextPort - 10
const fs = require('fs')
const express = require('express')
const next = require('next')
const helmet = require('helmet')
const noCache = require('nocache')
const httpProxy = require('express-http-proxy');
const proxy = require('http-proxy-middleware');
const routes = require('./routes')
const { join, resolve } = require('path')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = routes.getRequestHandler(app)
const buildEnv = process.env.DEPLOY_ENV || 'dev'
const { assetPrefix, $assets } = require(`./next.${buildEnv}.config`)
const spawn = require('cross-spawn')
const chalk = require('chalk')
const xmpieBuild = fs.existsSync('./.xmpie')
const fetch = require('node-fetch')

require('./ustore-internal/scripts/applyFeaturesConfig')

const argv = (str) => {
  const idx = process.argv.findIndex((a) => a.startsWith(str))
  if (idx > -1) {
    return process.argv[idx].substring(str.length + 1)
  }
  return null
}

const ducBuild = argv('ducbuild')
const ducsPath = ducBuild && resolve(ducBuild === '1' ? '../ustore-ducs' : ducBuild)

const ducsConfig = {
  root: ducsPath,
  dist_dev: ducBuild && join(ducsPath, 'dist_dev')
}

const uStoreServerUrl = argv('server') || 'http://uStoreNG.xmpie.net' // 'http://frontend1'

const proxyDirectories = ['/ustore', '/uStore', '/uStoreRestAPI', '/uStoreThemeCustomizations', '/uStoreThemes', '/favicon.ico']

const getWidgets = async () => {
  const res = await fetch(`${uStoreServerUrl.startsWith('http') ? '' : 'http://'}${uStoreServerUrl}/uStoreRestAPI/v1/system/properties/form/widgets`)
  return res.text()
}

const makeHttpProxy = (base) => httpProxy(`${uStoreServerUrl}`,
  {
    https: false,
    proxyReqPathResolver: (req) => base + req.url,
  }
)

// Spins a process for compiling the DUC project.
if (ducBuild) {
  console.log(chalk.green('Start DUC build process'))
  spawn('npm', ['--prefix', ducsConfig.root, 'start'], { stdio: 'inherit' })
}

// Allows running the client only version under the out directory
// This is to enable testing the client only build.
if (argv('client')) {
  console.log('\x1b[31m%s\x1b[0m', '=====! Using exported directory !=====');
  const proxyServer = express();

  // create a proxy that will redirect all assets request to the out directory
  proxyServer.use(
    '/',
    proxy({
      target: `http://localhost:${nextPort}`,
      pathRewrite: {
        [`^${assetPrefix}`]: '/'
      }
    })
  );


  proxyServer.listen(proxyPort, proxyError => {
    if (proxyError) throw proxyError;

    const nextServer = express()

    nextServer.use(noCache())
    nextServer.use(helmet.frameguard())

    //serve static files from the out directory
    if (dev) {
      nextServer.use(express.static(__dirname + '/out'))
      nextServer.use('/webcomponents', express.static(join(__dirname, './webcomponents')))
      nextServer.use('/ducs', express.static(join(__dirname, './ducs')))

      proxyDirectories.forEach(p => nextServer.use(p, makeHttpProxy(p)))
    }
    // all requests to the server should respond with the index.html
    // this enabled the client sides routing
    nextServer.get('*', (req, res) => {
      res.sendFile(__dirname + '/out/index.html')
    })


    nextServer.listen(nextPort, (err) => {
      if (err) throw err
      console.log(`next > Ready on http://localhost:${proxyPort}`)
    })
  });
} else {
  // This is the normal development server of nextjs
  const proxyServer = express();

  // Create a proxy server with url rewrite for the asset prefix
  proxyServer.use(
    '/',
    proxy({
      target: `http://localhost:${nextPort}`,
      pathRewrite: {
        [`^${assetPrefix}`]: '/'
      }
    })
  );

  proxyServer.listen(proxyPort, proxyError => {
    if (proxyError) throw proxyError;

    app.prepare()
      .then(() => {
        const nextServer = express()

        // set the asset prefix for the nextjs application
        app.setAssetPrefix(`http://localhost:${proxyPort}${assetPrefix}`);

        nextServer.use(noCache())
        nextServer.use(helmet.frameguard())

        // serve  static assets from global directories and directories inside the theme.
        if (dev) {
          console.log('Dev server is serving static files')
          nextServer.use(`/assets`, express.static($assets))
          nextServer.use('/static', express.static(join(__dirname, '/static')))
          nextServer.use('/static-internal', express.static(join(__dirname, '/ustore-internal/static')))
          nextServer.use('webcomponents', express.static(join(__dirname, './webcomponents')))
          if (ducBuild) {
            nextServer.use('/ducs', express.static(ducsConfig.dist_dev))
            nextServer.use('/uStoreRestAPI/v1/system/properties/form/widgets', async (req, res, next) => {
              const dirs = fs.readdirSync(ducsConfig.dist_dev)
              const ducs = dirs.filter(dir => dir !== 'Sample' || !xmpieBuild).map(dir => ({name: dir, baseUrl: `/ducs/${dir}`}))
              if (xmpieBuild) {
                res.send(`var xmpie_uStore_DUCs = ${JSON.stringify(ducs)}`)
              } else {
                const widgetScript = await getWidgets()
                res.send(`${widgetScript}; xmpie_uStore_DUCs = [...xmpie_uStore_DUCs, ...${JSON.stringify(ducs)}];`)
              }
            })
          }
          proxyDirectories.forEach(p => nextServer.use(p, makeHttpProxy(p)))
        }

        // all requests are processed by the next application
        nextServer.get('*', (req, res) => {
          return handle(req, res)
        })

        nextServer.listen(nextPort, (err) => {
          if (err) throw err
          console.log(`next > Ready on http://localhost:${proxyPort}`)
        })
      })
      .catch((ex) => {
        console.error(ex.stack)
        process.exit(1)
      })
  })
}
