// vue.config.js
const path = require('path')
const webpack = require('webpack')
const RemoveStrictPlugin = require('remove-strict-webpack-plugin')
const fs = require('fs')
const SentryPlugin = require('@sentry/webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin')
const merge = require('webpack-merge')
const VueConfigPages = require('./vue.config.pages')
const ImageminPlugin = require('imagemin-webpack-plugin').default
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CompressionPlugin = require('compression-webpack-plugin')
const exportEnv = require('./src/helpers/export-env')
const os = require('os')
const devMode = process.env.NODE_ENV !== 'production'
const publicPath = process.env.VUE_APP_PUBLIC_PATH || false
const sourceMap = process.env.VUE_APP_ENABLE_SOURCEMAP ? process.env.VUE_APP_ENABLE_SOURCEMAP === 'true' : false
const devTool = process.env.VUE_APP_DEVTOOL ? process.env.VUE_APP_DEVTOOL : 'cheap-source-map'
const isEvo = process.env.VUE_APP_APPLICATION_NAME === 'EVO'

const pwaConfigs = {
  manifestPath: isEvo ? 'evo-manifest.json' : 'ibs-manifest.json',
  manifestOptions: require(`./public/${isEvo ? 'evo' : 'ibs'}-manifest.json`),
}

function resolve(dir) {
  return path.join(__dirname, dir)
}

module.exports = {
  // Vue cli MultiPage setup
  publicPath: !devMode && publicPath ? publicPath : '/',
  pages: VueConfigPages.getPages(),
  productionSourceMap: true,
  configureWebpack: config => {
    config = {
      devtool: devTool,
      resolve: {
        // load vue-loader read .js .vue .json files
        extensions: ['.js', '.vue', '.json'],
        // add alias
        alias: {
          vue$: 'vue/dist/vue.esm.js',
          '@': resolve('src'),
          '@@': resolve('src/thirdparty/eshop'),
          '@@@': resolve('src/thirdparty/placement-tree-viewer'),
          '@@@@': resolve('src/thirdparty/payment'),
          '@AppCenter': resolve('src/thirdparty/elken-app-center'),
          vue: 'vue/dist/vue.esm.js',
        },
      },
      // use jquery
      plugins: [
        new exportEnv({ filename: 'env-vars.js' }),
        new webpack.ProvidePlugin({
          $: 'jquery',
          jquery: 'jquery',
          'window.jQuery': 'jquery',
          jQuery: 'jquery',
        }),
        new ImageminPlugin({
          test: /\.(jpe?g|png|gif|svg)$/i,
          disable: devMode,
        }),
        new MiniCssExtractPlugin({
          filename: devMode ? '[name].css' : '[name].[hash].css',
          chunkFilename: devMode ? '[name].[id].css' : '[name].[id].[hash].css',
        }),
      ],
    }

    // Development -----------------------------------------------------------------------------------------------------
    if (devMode) {
      config.devServer = {
        host: process.env.VUE_APP_HOST || '0.0.0.0',
        port: process.env.VUE_APP_PORT || '8080',
        open: true,
        disableHostCheck: true,
        hot: true,
        inline: false,
        // Todo enabled if history mode
        // historyApiFallback: {
        //   rewrites: [
        //     { from: /^\/products\/?.*/, to: path.posix.join('/', '/products/index.html') },
        //     { from: /^\/checkout\/?.*/, to: path.posix.join('/', '/checkout/index.html') },
        //     { from: /./, to: path.posix.join('/', 'index.html') },
        //   ],
        // },
        allowedHosts: [process.env.VUE_APP_HOST],
      }

      if (process.env.VUE_APP_HTTPS === 'true') {
        config.devServer = merge(config.devServer, {
          https: {
            key: fs.readFileSync(resolve('certs/localhost.key'), 'utf8'),
            cert: fs.readFileSync(resolve('certs/localhost.crt'), 'utf8'),
          },
        })
      }
    }

    // PRODUCTION ------------------------------------------------------------------------------------------------------
    if (!devMode) {
      config.optimization = {
        // minimize: false, // Enable to debug code in production
        minimizer: [
          new TerserPlugin({
            sourceMap: sourceMap,
            parallel: true,
            extractComments: true,
            cache: true,
            terserOptions: {
              output: {
                comments: false,
              },
              safari10: true,
              compress: {
                inline: 0,
              },
              mangle: false,
            },
          }),
        ],
      }
      config.plugins.push(
        // Remove strict on build. Support for safari 8 or old browsers
        new RemoveStrictPlugin()
      )
    }

    // enable gzip (experimental)
    if (process.env.VUE_APP_ENABLE_GZIP === 'true') {
      config.plugins.push(
        new CompressionPlugin({
          filename: '[path].gz[query]',
          algorithm: 'gzip',
          test: /\.(js|css|html|svg)$/,
          cache: true,
          minRatio: 0.6,
          compressionOptions: { level: 11 },
        })
      )
    }

    // add sentry login
    if (process.env.VUE_APP_LOG_SENTRY === 'true') {
      config.plugins.push(
        new SentryPlugin({
          release: require(path.join(__dirname, '/package.json')).version,
          include: './dist',
          ignore: ['node_modules', 'webpack.config.js'],
        })
      )
    }
    return config
  },

  chainWebpack: config => {
    // Webpack chunks optimizations
    config.optimization.splitChunks({
      cacheGroups: VueConfigPages.getPagesSplitChunkCacheGroupsOptimizations(),
    })
    // Change the sass loader from vue-style-loader to fast-sass-loader for build
    // performance, however fast-sass-loader dose this by merging all the code into
    // one file and caching the file. Which leverages the ability to produce
    // sourcemaps

    config.module.rules.delete('scss')
    let scssRule = config.module.rule('scss').test(/\.scss$/)

    ;[
      { name: MiniCssExtractPlugin.loader },
      { name: 'css-loader' },
      { name: 'postcss-loader' },
      { name: 'fast-sass-loader' },
    ].forEach(load => {
      scssRule
        .use(load.name)
        .loader(load.loader || load.name)
        .options(load.options || {})
    })

    // GraphQL Loader to dynamically generate responsive images
    config.module
      .rule('responsive-loader')
      .test(/\.(jpe?g|png)\?$/i)
      .use('responsive-loader')
      .loader('responsive-loader')
      .end()

    // Remove the default typescript loader to allow .ts and .js to co-exist
    const rule = config.module.rule('ts')

    rule.uses.delete('thread-loader')
    rule
      .use('ts-loader')
      .loader('ts-loader')
      .tap(options => {
        options.transpileOnly = false
        options.happyPackMode = false

        return options
      })

    if (!devMode) {
      // remove type checking on production
      config.plugins.delete('fork-ts-checker')
    } else {
      // increase memory for type checking on dev
      config.plugin('fork-ts-checker').tap(args => {
        let totalmem = Math.floor(os.totalmem() / 1024 / 1024) //get OS mem size
        args[0].memoryLimit = totalmem > 4200 ? 4096 : 2048
        return args
      })
    }
  },
  transpileDependencies: [
    'bootstrap-vue', // not being transpile to ES5 causes failing in Safari 8
    'vue-bootstrap-slider', // not being transpile to ES5 causes failing in Safari 8
  ],
  css: {
    // sourceMap: process.env.NODE_ENV === 'development' && process.env.VUE_APP_CSS_SOURCE_MAP !== 'false',
    loaderOptions: {
      // pass options to sass-loader
      sass: {
        // @/ is an alias to src/
        // so this assumes you have a file named `src/variables.scss`
        data: ``,
        sassOptions: {
          outputStyle: 'compressed',
        },
      },
    },
  },
  pwa: {
    themeColor: '#071241',
    msTileColor: '#071241',
    appleMobileWebAppCapable: 'yes',
    workboxPluginMode: 'InjectManifest',
    workboxOptions: {
      swSrc: 'src/service-worker.js',
      exclude: [/\.map$/, /manifest\.json$/, '.htaccess', '.gitkeep', 'gitignore'],
    },
    ...pwaConfigs,
  },
}
