text: "use strict";
  var __extends = (this && this.__extends) || (function () {
      var extendStatics = function (d, b) {
          extendStatics = Object.setPrototypeOf ||
              ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
              function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
          return extendStatics(d, b);
      }
      return function (d, b) {
          extendStatics(d, b);
          function __() { this.constructor = d; }
          d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
      };
  })();
  Object.defineProperty(exports, "__esModule", { value: true });
  var ts = require("typescript");
  var Lint = require("tslint");
  var tsutils = require("tsutils");
  var Utils_1 = require("./utils/Utils");
  var TypeGuard_1 = require("./utils/TypeGuard");
  var Rule = (function (_super) {
      __extends(Rule, _super);
      function Rule() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      Rule.prototype.apply = function (sourceFile) {
          return this.applyWithFunction(sourceFile, walk, this.parseOptions(this.getOptions()));
      };
      Rule.prototype.parseOptions = function (options) {
          var _this = this;
          var result = {
              replacements: {},
              ignoredList: [],
              config: {
                  ignoreExternalModule: true,
                  case: StringCase.camel
              }
          };
          if (options.ruleArguments instanceof Array) {
              options.ruleArguments.forEach(function (opt, index) {
                  if (index === 1 && TypeGuard_1.isObject(opt)) {
                      result.replacements = _this.extractReplacements(opt);
                  }
                  if (index === 2 && Array.isArray(opt)) {
                      result.ignoredList = _this.extractIgnoredList(opt);
                  }
                  if (index === 3 && TypeGuard_1.isObject(opt)) {
                      result.config = _this.extractConfig(opt);
                  }
              });
          }
          return result;
      };
      Rule.prototype.extractReplacements = function (opt) {
          var result = {};
          if (TypeGuard_1.isObject(opt)) {
              Object.keys(opt).forEach(function (key) {
                  var value = opt[key];
                  if (typeof value === 'string') {
                      result[key] = value;
                  }
              });
          }
          return result;
      };
      Rule.prototype.extractIgnoredList = function (opt) {
          return opt.filter(function (moduleName) { return typeof moduleName === 'string'; });
      };
      Rule.prototype.extractConfig = function (opt) {
          var result = { ignoreExternalModule: true, case: StringCase.camel };
          var configKeyList = ['ignoreExternalModule', 'case'];
          if (TypeGuard_1.isObject(opt)) {
              return Object.keys(opt).reduce(function (accum, key) {
                  if (configKeyList.filter(function (configKey) { return configKey === key; }).length >= 1) {
                      accum[key] = opt[key];
                      return accum;
                  }
                  return accum;
              }, { ignoreExternalModule: true, case: StringCase.camel });
          }
          return result;
      };
      Rule.metadata = {
          ruleName: 'import-name',
          type: 'maintainability',
          description: 'The name of the imported module must match the name of the thing being imported',
          hasFix: true,
          options: null,
          optionsDescription: '',
          optionExamples: [
              [true],
              [true, { moduleName: 'importedName' }],
              [true, { moduleName: 'importedName' }, ['moduleName1', 'moduleName2']],
              [true, { moduleName: 'importedName' }, ['moduleName1', 'moduleName2'], { ignoreExternalModule: false }]
          ],
          typescriptOnly: true,
          issueClass: 'Ignored',
          issueType: 'Warning',
          severity: 'Low',
          level: 'Opportunity for Excellence',
          group: 'Clarity',
          commonWeaknessEnumeration: '710'
      };
      return Rule;
  }(Lint.Rules.AbstractRule));
  exports.Rule = Rule;
  var StringCase;
  (function (StringCase) {
      StringCase["any"] = "any-case";
      StringCase["pascal"] = "PascalCase";
      StringCase["camel"] = "camelCase";
  })(StringCase || (StringCase = {}));
  function walk(ctx) {
      var option = ctx.options;
      function getNameNodeFromImportNode(node) {
          if (tsutils.isImportEqualsDeclaration(node)) {
              return node.name;
          }
          var importClause = node.importClause;
          return importClause === undefined ? undefined : importClause.name;
      }
      function checkIgnoreExternalModule(moduleName, node, opt) {
          var runtimeNode = node;
          if (opt.ignoreExternalModule === true && runtimeNode.parent !== undefined && runtimeNode.parent.resolvedModules !== undefined) {
              var ignoreThisExternalModule_1 = false;
              runtimeNode.parent.resolvedModules.forEach(function (value, key) {
                  if (key === moduleName && value.isExternalLibraryImport === true) {
                      ignoreThisExternalModule_1 = true;
                  }
              });
              return ignoreThisExternalModule_1;
          }
          return false;
      }
      function checkIgnoredListExists(moduleName, ignoredList) {
          return ignoredList.filter(function (ignoredModule) { return ignoredModule === moduleName; }).length >= 1;
      }
      function checkReplacementsExist(importedName, expectedImportedName, moduleName, replacements) {
          var allowedReplacementKeys = [
              makeCamelCase(expectedImportedName),
              makePascalCase(expectedImportedName),
              moduleName,
              moduleName.replace(/.*\//, '')
          ];
          return Utils_1.Utils.exists(Object.keys(replacements), function (replacementKey) {
              for (var index = 0; allowedReplacementKeys.length > index; index = index + 1) {
                  if (replacementKey === allowedReplacementKeys[index]) {
                      return importedName === replacements[replacementKey];
                  }
              }
              return false;
          });
      }
      function isImportNameValid(importedName, expectedImportedName, moduleName, node) {
          if (transformName(expectedImportedName).indexOf(importedName) > -1) {
              return true;
          }
          var isReplacementsExist = checkReplacementsExist(importedName, expectedImportedName, moduleName, option.replacements);
          if (isReplacementsExist) {
              return true;
          }
          var isIgnoredModuleExist = checkIgnoredListExists(moduleName, option.ignoredList);
          if (isIgnoredModuleExist) {
              return true;
          }
          var ignoreThisExternalModule = checkIgnoreExternalModule(moduleName, node, option.config);
          if (ignoreThisExternalModule) {
              return true;
          }
          return false;
      }
      function transformName(input) {
          switch (option.config.case) {
              case StringCase.camel:
                  return [makeCamelCase(input)];
              case StringCase.pascal:
                  return [makePascalCase(input)];
              case StringCase.any:
                  return [makeCamelCase(input), makePascalCase(input)];
              default:
                  throw new Error("Unknown case for import-name rule: \"" + option.config.case + "\"");
          }
      }
      function makeCamelCase(input) {
          return input.replace(/[-|\.|_](.)/g, function (_match, group1) {
              return group1.toUpperCase();
          });
      }
      function makePascalCase(input) {
          return input.replace(/(?:^|[-|\.|_|])([a-z])/g, function (_, group1) { return group1.toUpperCase(); });
      }
      function validateImport(node, importedName, moduleName) {
          var expectedImportedName = moduleName.replace(/.*\//, '');
          if (expectedImportedName === '' || expectedImportedName === '.' || expectedImportedName === '..') {
              return;
          }
          if (isImportNameValid(importedName, expectedImportedName, moduleName, node)) {
              return;
          }
          var expectedImportedNames = transformName(expectedImportedName);
          var expectedNames = expectedImportedNames.map(function (name) { return "'" + name + "'"; }).join(' or ');
          var message = "Misnamed import. Import should be named " + expectedNames + " but found '" + importedName + "'";
          var nameNode = getNameNodeFromImportNode(node);
          if (nameNode === undefined) {
              return;
          }
          var nameNodeStartPos = nameNode.getStart();
          var fix = new Lint.Replacement(nameNodeStartPos, nameNode.end - nameNodeStartPos, expectedImportedNames[0]);
          ctx.addFailureAt(node.getStart(), node.getWidth(), message, fix);
      }
      function cb(node) {
          if (tsutils.isImportEqualsDeclaration(node)) {
              var name_1 = node.name.text;
              if (tsutils.isExternalModuleReference(node.moduleReference)) {
                  var moduleRef = node.moduleReference;
                  if (tsutils.isStringLiteral(moduleRef.expression)) {
                      var moduleName = moduleRef.expression.text;
                      validateImport(node, name_1, moduleName);
                  }
              }
              else if (tsutils.isQualifiedName(node.moduleReference)) {
                  var moduleName = node.moduleReference.getText();
                  moduleName = moduleName.replace(/.*\./, '');
                  validateImport(node, name_1, moduleName);
              }
          }
          if (tsutils.isImportDeclaration(node)) {
              if (node.importClause !== undefined && node.importClause.name !== undefined) {
                  var name_2 = node.importClause.name.text;
                  if (tsutils.isStringLiteral(node.moduleSpecifier)) {
                      var moduleName = node.moduleSpecifier.text;
                      validateImport(node, name_2, moduleName);
                  }
              }
          }
          return ts.forEachChild(node, cb);
      }
      return ts.forEachChild(ctx.sourceFile, cb);
  }
  //# sourceMappingURL=importNameRule.js.map