// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:args/args.dart' show ArgParser, ArgResults;
import 'package:path/path.dart' as p;

import '../js_ast/js_ast.dart';
import 'js_names.dart';

/// The module format to emit.
enum ModuleFormat {
  /// ECMAScript 6 module using import and export.
  es6,

  /// CommonJS module (used in Node.js)
  common,

  /// Asynchronous Module Definition (AMD, used in browsers).
  amd,

  /// Dart Dev Compiler's own format.
  ddc,
}

/// Parses a string into a [ModuleFormat].
ModuleFormat parseModuleFormat(String s) => {
      'es6': ModuleFormat.es6,
      'common': ModuleFormat.common,
      'amd': ModuleFormat.amd,
      'ddc': ModuleFormat.ddc,
      // Deprecated:
      'node': ModuleFormat.common,
      'legacy': ModuleFormat.ddc
    }[s];

/// Parse the module format option added by [addModuleFormatOptions].
List<ModuleFormat> parseModuleFormatOption(ArgResults args) {
  return (args['modules'] as List<String>).map(parseModuleFormat).toList();
}

/// Adds an option to the [argParser] for choosing the module format, optionally
/// [allowMultiple] formats to be specified, with each emitted into a separate
/// file.
void addModuleFormatOptions(ArgParser argParser, {bool hide = true}) {
  argParser.addMultiOption('modules', help: 'module pattern to emit', allowed: [
    'es6',
    'common',
    'amd',
    'ddc',
    'legacy', // renamed to ddc
    'node', // renamed to commonjs
    'all' // to emit all flavors for the SDK
  ], allowedHelp: {
    'es6': 'ECMAScript 6 modules',
    'common': 'CommonJS/Node.js modules',
    'amd': 'AMD/RequireJS modules'
  }, defaultsTo: [
    'amd'
  ]);
}

/// Transforms an ES6 [module] into a given module [format].
///
/// If the format is [ModuleFormat.es6] this will return [module] unchanged.
///
/// Because JS ASTs are immutable the resulting module will share as much
/// structure as possible with the original. The transformation is a shallow one
/// that affects the top-level module items, especially [ImportDeclaration]s and
/// [ExportDeclaration]s.
Program transformModuleFormat(ModuleFormat format, Program module) {
  switch (format) {
    case ModuleFormat.ddc:
      return DdcModuleBuilder().build(module);
    case ModuleFormat.common:
      return CommonJSModuleBuilder().build(module);
    case ModuleFormat.amd:
      return AmdModuleBuilder().build(module);
    case ModuleFormat.es6:
    default:
      return module;
  }
}

/// Base class for compiling ES6 modules into various ES5 module patterns.
///
/// This is a helper class for utilities and state that is shared by several
/// module transformers.
// TODO(jmesserly): "module transformer" might be a better name than builder.
abstract class _ModuleBuilder {
  final imports = <ImportDeclaration>[];
  final exports = <ExportDeclaration>[];
  final statements = <Statement>[];

  /// Collect [imports], [exports] and [statements] from the ES6 [module].
  ///
  /// For exports, this will also add their body to [statements] in the
  /// appropriate position.
  void visitProgram(Program module) {
    for (var item in module.body) {
      if (item is ImportDeclaration) {
        visitImportDeclaration(item);
      } else if (item is ExportDeclaration) {
        visitExportDeclaration(item);
      } else if (item is Statement) {
        visitStatement(item);
      }
    }
  }

  void visitImportDeclaration(ImportDeclaration node) {
    imports.add(node);
  }

  void visitExportDeclaration(ExportDeclaration node) {
    exports.add(node);
    var exported = node.exported;
    if (exported is! ExportClause) {
      statements.add(exported.toStatement());
    }
  }

  void visitStatement(Statement node) {
    statements.add(node);
  }
}

/// Generates modules for with our DDC `dart_library.js` loading mechanism.
// TODO(jmesserly): remove this and replace with something that interoperates.
class DdcModuleBuilder extends _ModuleBuilder {
  Program build(Program module) {
    // Collect imports/exports/statements.
    visitProgram(module);

    // Build import parameters.
    var exportsVar = TemporaryId('exports');
    var parameters = <TemporaryId>[exportsVar];
    var importNames = <Expression>[];
    var importStatements = <Statement>[];
    for (var import in imports) {
      importNames.add(import.from);
      // TODO(jmesserly): we could use destructuring here.
      var moduleVar =
          TemporaryId(pathToJSIdentifier(import.from.valueWithoutQuotes));
      parameters.add(moduleVar);
      for (var importName in import.namedImports) {
        assert(!importName
            .isStar); // import * not supported in ddc format modules.
        var asName = importName.asName ?? importName.name;
        var fromName = importName.name.name;
        // Load non-SDK modules on demand (i.e., deferred).
        if (import.from.valueWithoutQuotes != dartSdkModule) {
          importStatements.add(js.statement(
              'let # = dart_library.defer(#, #, function (mod, lib) {'
              '  # = mod;'
              '  # = lib;'
              '});',
              [asName, moduleVar, js.string(fromName), moduleVar, asName]));
        } else {
          importStatements.add(js.statement(
              'const # = #.#', [asName, moduleVar, importName.name.name]));
        }
      }
    }
    statements.insertAll(0, importStatements);

    if (exports.isNotEmpty) {
      statements.add(js.comment('Exports:'));
      // TODO(jmesserly): make these immutable in JS?
      for (var export in exports) {
        var names = export.exportedNames;
        assert(names != null); // export * not supported in ddc modules.
        for (var name in names) {
          var alias = name.asName ?? name.name;
          statements.add(
              js.statement('#.# = #;', [exportsVar, alias.name, name.name]));
        }
      }
    }

    var functionName =
        'load__' + pathToJSIdentifier(module.name.replaceAll('.', '_'));
    var resultModule = NamedFunction(
        Identifier(functionName),
        js.fun("function(#) { 'use strict'; #; }", [parameters, statements]),
        true);

    var moduleDef = js.statement('dart_library.library(#, #, #, #)', [
      js.string(module.name, "'"),
      LiteralNull(),
      js.commentExpression(
          'Imports', ArrayInitializer(importNames, multiline: true)),
      resultModule
    ]);
    return Program(<ModuleItem>[moduleDef]);
  }
}

/// Generates CommonJS modules (used by Node.js).
class CommonJSModuleBuilder extends _ModuleBuilder {
  Program build(Program module) {
    var importStatements = [
      js.statement("'use strict';"),
    ];

    // Collect imports/exports/statements.
    visitProgram(module);

    for (var import in imports) {
      // TODO(jmesserly): we could use destructuring here.
      var moduleVar =
          TemporaryId(pathToJSIdentifier(import.from.valueWithoutQuotes));
      importStatements
          .add(js.statement('const # = require(#);', [moduleVar, import.from]));

      // TODO(jmesserly): optimize for the common case of a single import.
      for (var importName in import.namedImports) {
        // import * is not emitted by the compiler, so we don't support it here.
        assert(!importName.isStar);
        var asName = importName.asName ?? importName.name;
        importStatements.add(js.statement(
            'const # = #.#', [asName, moduleVar, importName.name.name]));
      }
    }
    statements.insertAll(0, importStatements);

    if (exports.isNotEmpty) {
      var exportsVar = Identifier('exports');
      statements.add(js.comment('Exports:'));
      for (var export in exports) {
        var names = export.exportedNames;
        // export * is not emitted by the compiler, so we don't handle it here.
        assert(names != null);
        for (var name in names) {
          var alias = name.asName ?? name.name;
          statements.add(
              js.statement('#.# = #;', [exportsVar, alias.name, name.name]));
        }
      }
    }

    return Program(statements);
  }
}

/// Generates AMD modules (used in browsers with RequireJS).
class AmdModuleBuilder extends _ModuleBuilder {
  AmdModuleBuilder();

  Program build(Program module) {
    var importStatements = <Statement>[];

    // Collect imports/exports/statements.
    visitProgram(module);

    var dependencies = <LiteralString>[];
    var fnParams = <Parameter>[];
    for (var import in imports) {
      // TODO(jmesserly): we could use destructuring once Atom supports it.
      var moduleVar =
          TemporaryId(pathToJSIdentifier(import.from.valueWithoutQuotes));
      fnParams.add(moduleVar);
      dependencies.add(import.from);

      // TODO(jmesserly): optimize for the common case of a single import.
      for (var importName in import.namedImports) {
        // import * is not emitted by the compiler, so we don't handle it here.
        assert(!importName.isStar);
        var asName = importName.asName ?? importName.name;
        importStatements.add(js.statement(
            'const # = #.#', [asName, moduleVar, importName.name.name]));
      }
    }
    statements.insertAll(0, importStatements);

    if (exports.isNotEmpty) {
      var exportedProps = <Property>[];
      for (var export in exports) {
        var names = export.exportedNames;
        // export * is not emitted by the compiler, so we don't handle it here.
        assert(names != null);
        for (var name in names) {
          var alias = name.asName ?? name.name;
          exportedProps.add(Property(js.string(alias.name), name.name));
        }
      }
      statements.add(js.comment('Exports:'));
      statements.add(Return(ObjectInitializer(exportedProps, multiline: true)));
    }

    // TODO(vsm): Consider using an immediately invoked named function pattern
    // (see ddc module code above).
    var block = js.statement("define(#, function(#) { 'use strict'; #; });",
        [ArrayInitializer(dependencies), fnParams, statements]);

    return Program([block]);
  }
}

/// Converts an entire arbitrary path string into a string compatible with
/// JS identifier naming rules while conserving path information.
///
/// NOT guaranteed to result in a unique string. E.g.,
///   1) '__' appears in a file name.
///   2) An escaped '/' or '\' appears in a filename (a/b and a$47b).
String pathToJSIdentifier(String path) {
  path = p.normalize(path);
  if (path.startsWith('/') || path.startsWith('\\')) {
    path = path.substring(1, path.length);
  }
  return toJSIdentifier(path
      .replaceAll('\\', '__')
      .replaceAll('/', '__')
      .replaceAll('..', '__')
      .replaceAll('-', '_'));
}

// Replacement string for path separators (i.e., '/', '\', '..').
final encodedSeparator = '__';
