'use strict';
const path = require('path');
const assign = require('object-assign');
const fs = require('fs');

/**
 * @class
 * @param {Object} options
 * @param {String} options.path Path to theme folder, required param
 * @param {RegExp} [options.rule=/^@theme/]
 * @param {String} [options.env='THEME']
 * @param {String} [options.defaultTheme='default']
 * @param {String} [options.theme]
 * @constructor
 */

function WpjResolverPlugin(options) {
   this.options = assign(
      {},
      {
         rule: /^@theme/,
         paths: {},
         scss: false
      },
      options
   );

   this.options.moduleRule = new RegExp(this.options.rule.source + '\\[(.*)\\]');
}

WpjResolverPlugin.prototype.apply = function(compiler) {
   const options = this.options;

   var target = compiler.ensureHook('internal-resolve');

   var root = fs.realpathSync('.');

   const resolve = (file, request, resolveContext, finalCallback) => {
      const obj = assign({}, request, {
         request: './' + file,
         path: root,
         relativePath: '.',
      });

      // console.log('Resolving', request.request, file);
      compiler.doResolve(target, obj, `found file: ${file}`, resolveContext, function(...args) {
         return finalCallback(...args);
      });
   };

   const resolveFiles = (files, request, resolveContext, finalCallback) => {
      let resolved = false;
      files.some(file => {
         if (
            (fs.existsSync(file) && fs.lstatSync(file).isFile()) ||
            (fs.existsSync(file + '.scss') && fs.lstatSync(file + '.scss').isFile()) ||
            (fs.existsSync(file + '.tsx') && fs.lstatSync(file + '.tsx').isFile()) ||
            (fs.existsSync(file + '.ts') && fs.lstatSync(file + '.ts').isFile())
         ) {
            resolved = true;
            resolve(file, request, resolveContext, finalCallback);
            return true;
         }
      });

      if (!resolved) {
         return finalCallback();
      }
   };

   compiler.getHook('raw-resolve').tapAsync('WpjResolverPlugin', function(request, resolveContext, finalCallback) {
      if (!options.rule.test(request.request)) {
         return finalCallback();
      }

      let attempts = assign({}, options.paths);

      let moduleMatch = request.request.match(options.moduleRule);
      if (moduleMatch) {
         attempts = {};
         attempts[moduleMatch[1]] = options.paths[moduleMatch[1]];
      }

      let files = [];

      Object.keys(attempts).forEach(name => {
         let prefix = attempts[name];
         files.push(request.request.replace(moduleMatch ? options.moduleRule : options.rule, prefix));

         if (options.scss) {
            let parts = path.parse(request.request);
            files.push(
               path.join(parts.dir.replace(moduleMatch ? options.moduleRule : options.rule, prefix), '_' + parts.base)
            );
         }
      });

      return resolveFiles(files, request, resolveContext, finalCallback);
   });
};

module.exports = WpjResolverPlugin;
