const maps = true;
var env = process.env;
const pack = require('./pack.production');
const dir = function(...args) {
  return path.posix.join.apply(path, ['./', ...args])
};
const fs = require( 'fs' );
var path = require('path');

var bCore = require( "@babel/core" );

var loadList = [dir(pack.src, pack.entry.js)];
var loaded = {};

let searchFile = function(base, name) {
  if(fs.existsSync(name))
    return name;

  let option;
  if(base === 'C:\\code\\kus-front-new/src/view/cmp/switch/Switch.jsx')
    debugger
  if(name[0] ==='/'){
    option = dir(pack.src, name.substr(1));
    if(fs.existsSync(option))
      return option;

    option = dir(pack.src, name.substr(1))+'.jsx';
    if(fs.existsSync(option))
      return option;
  }else if(name[0] === '.'){
    option = path.posix.join(path.dirname(base), name)
    if(fs.existsSync(option))
      return option;

    option = path.posix.join(path.dirname(base), name)+'.jsx'
    if(fs.existsSync(option))
      return option;
  }else {
    option = path.posix.join(path.dirname(base), name);
    if(fs.existsSync(option))
      return option;

    option = path.posix.join(path.dirname(base), name)+'.jsx'
    if(fs.existsSync(option))
      return option;
  }

  console.log('gmm', base, name);
};
let idx = 13;
let idxes = {};
var sass = require('node-sass');

let getAllDeps = async function(parent, out, loadList, hash) {
  out = out || [];
  hash = hash || {};
  let resolved = [];
  //for( let i = loadList.length-1; i >= 0; i-- ){
  for( let i = 0, _i = loadList.length; i < _i; i++ ){
    let textIDX = idx.toString(36);
    let isSVG = false;
    if(loadList[i][0] !== '.' && loadList[i][0] !== '/'){
      loadList[i] = '/'+loadList[i];
    }
    const loadListElement = {fileName: searchFile(parent, loadList[ i ]), name: loadList[ i ], compacted: textIDX, deps: {}};
    idxes[textIDX] = loadListElement;
    idx++;
    resolved[i] = loadListElement;
    out.push(loadListElement);


    if(!loadListElement.fileName){
      console.error(`Unresolved dependency \`${loadList[i]}\` from \`${parent}\``);
      loadListElement.compacted = 'a';
      continue;
    }




    if(loadListElement.fileName in hash){
      resolved[i] = hash[loadListElement.fileName];
      continue;
    }

    hash[loadListElement.fileName] = loadListElement;

    let fileData = fs.readFileSync(loadListElement.fileName, 'utf-8');

    if(loadListElement.fileName.substr(-4)==='.svg'){
      fileData = `const SVG = D.declare("${
        textIDX
      }", (cfg)=>{ return ${
        (fileData+'')
          .replace(/(<svg[^>]+"\s*)>/i,'$1 {...cfg}>')
      }; });
            export default SVG;
            `;
      isSVG = true;
    }


    if(loadListElement.fileName.substr(-5)==='.scss'){

      loadListElement.compacted='a';

      let cssData = await new Promise(function(r, j){
        let dir = pack.src;
        sass.render( {
          data: ( pack && pack.scss && pack.scss.shared || '' ) + ';\n' + fileData + '',
          file: loadListElement.fileName,
          sourceMap: maps,
          importer: function( url, prev, done ){

            if( url[ 0 ] === '/' ){
              url = path.join( __dirname, dir, url.substr( 1 ) );
            }
            var displayName = path.relative( path.join( __dirname, dir ), path.resolve( path.dirname( prev ), url ) )
            var name = path.resolve( path.dirname( prev ), url );


            let fName;
            let contents;
            try{
              contents = fs.readFileSync( name ) + '';
              done( {
                file: displayName, // only one of them is required, see section Special Behaviours.
                contents: contents
              } );
              return;
            }catch( e ){
            }
            res._log( 'Resolve scss dep ', url, 'for', fixedUrl );

            try{
              contents = fs.readFileSync( name + '.scss' ) + '';
              done( {
                file: displayName, // only one of them is required, see section Special Behaviours.
                contents: contents
              } );
              return;
            }catch( e ){
            }

            j( new Error( 'Can not resolve dependency!' ) )

          }
        }, function( err, result ){
          if( err ){
            const errorText = `Error at ${err.file}:\n` + err.formatted;
            return j( errorText )
          }
          r( result.css+'' )
        } );
      });
      loadListElement.code = cssData;
      continue
    }

    await new Promise(function(r, j) {
      bCore.transform( fileData,
        {
          "plugins": [
            [ "@babel/plugin-transform-react-jsx", {
              "pragma": isSVG ? "D.s":"D.h", // default pragma is React.createElement
              "pragmaFrag": "D.f", // default is React.Fragment
              "throwIfNamespace": false // defaults to true
            } ],
            ['@babel/plugin-transform-modules-amd']

          ],
          sourceFileName: textIDX,
          moduleId: textIDX
        }, async function( c, d, e ){
          if(c){
            console.log(c)
          }else{

            let them = (d.code.match(/define\([^\[]*\[([^\]]*)\]/)[1].split(',').map(a=>a.trim()).map(a=>a.substr(1)).map(a=>a.substr(0,a.length-1)));
            //them.length && console.log(them)

            let resolved = await getAllDeps(loadListElement.fileName, out, them.filter(a=>a && a!=='exports'), hash);
            for( var k = 0, _k = resolved.length; k < _k; k++ ){
              const resolvedElement = resolved[ k ];
              loadListElement.deps[resolvedElement.compacted] = true;
            }

            let index = 0;
            loadListElement.code = d.code.replace(/define\(([^[]*)\[([^\]]*)\]/, function(a, b, c) {
              return `define(${b}[${
                c.split(',')
                  .map(a=>a.trim())
                  .map(a=>a.substr(1))
                  .map(a=>a.substr(0,a.length-1))
                  .map((name)=>
                    name === 'exports' ? 'exports': resolved[index++].compacted
                  )
                  .map(name=>`"${name}"`)
                  .join(',')
              }]`;

            });

          }
          r()

        } );
    })


  }

  return resolved;
};
(async function() {
  let out = [];
  await getAllDeps('./',out, [dir(pack.entry.js)])
  let hash = {};
  let uniq = out.filter(function(f) {
    return !(f.fileName in hash) ?hash[f.fileName] = true: false;
  });
  let scss = [], js = [], svg = [];

  uniq.forEach(item=>{
    if(item.fileName === void 0)
      return;

    if(item.fileName.substr(-4) === '.svg'){
      svg.push(item);
    }else if(item.fileName.substr(-5) === '.scss'){
      scss.push(item);
    }else{
      js.push(item);
    }
  });
  try{
    fs.mkdirSync( pack.build, { recursive: true } );
    fs.mkdirSync( path.join(pack.public, pack.build), { recursive: true } );
  }catch(e){};

  var fJS = 'var jsLoader=function(){};define("a",[], function(){});'+svg.map(f=>f.code).join('\n');

  var outjsordered = [];
    let tolong = 0;
    let resolved = {a: true};

  svg.forEach(s=>resolved[s.compacted] = true);
  while(js.length && tolong<10000){
    tolong++;

    for( let i = js.length - 1; i >= 0; i-- ){
      const j = js[ i ];
      if(Object.keys(j.deps).filter(d=>!(d in resolved)).length === 0){
        outjsordered.push(js.splice(i, 1)[0]);
        resolved[j.compacted] = true;
      }

    }
  }

  console.log(tolong)
  fJS+=outjsordered.map(f=>f.code).join('\n');

  var Terser = require("terser");




  var html = fs.readFileSync(path.join(pack.src, pack.entry.jsDonor), 'utf-8');
  let inlining = [];
  var g = html.replace(/<script src="([^"]+)"/g, function(f, a) {
    if(a.indexOf('http')!==0){
      if(a.indexOf('build')===0)
        return '';
      // including
      var content;
      try{
        content = fs.readFileSync(path.join(pack.src, a), 'utf-8');
      }catch(e){
        content = fs.readFileSync(path.join(pack.public, a), 'utf-8');
      }
      inlining.push(content)
    }
  });

  fJS = inlining.join('\n')+fJS;

  fJS = await new Promise((r, j) => {

    bCore.transform(fJS, {
      "plugins": [
        '@babel/plugin-transform-modules-commonjs',
        ["@babel/plugin-transform-runtime",
          {
            "regenerator": false
          }
        ]
      ],
      presets: [
        [
          "@babel/preset-env",
          {
            useBuiltIns: 'usage',
            forceAllTransforms: true,
            corejs: {
              version: 3,
              proposals: false
            },
            "targets": {
              ie: "11",
              "browsers": ["last 2 versions"]
            }
          }
        ],
      ]
    }, function (c, d, e) {
      if (c)
        j(c)
      else
        r(d.code);
    });
  });

  fs.writeFileSync(path.join(pack.build, 'j.js'), fJS);
  var browserify = require('browserify');
  var b = browserify();
  b.add(path.join(pack.build, 'j.js'));

  fJS = await new Promise((r,j)=>{
    b.bundle(function(a,b,c) {
      if(a){
        console.log('Build error', a);
        j(a);
      }else{
        console.log('Build built');

        r(b);
      }
    })
  });
  let tersed = Terser.minify(fJS.toString('utf-8'));
  tersed.error && console.error(tersed.error);
  fJS = tersed.code;
  console.log('minified')

  fs.writeFileSync(path.join(pack.public, pack.build, 'j.js'), fJS);
  fs.writeFileSync(path.join(pack.build, 'c.css'), scss.map(f=>f.code).join('\n'));
  fs.writeFileSync(path.join(pack.public, pack.build, 'c.css'), scss.map(f=>f.code).join('\n'));


  console.log('SVG:', svg.length);
  console.log('SCSS:', scss.length);
  console.log('JS:',js.length);


  return;
  console.log(svg);
  console.log('\n');

  console.log(scss);
  console.log('\n');

  console.log(js)
  console.log('\n');
})();





