import _regeneratorRuntime from "@babel/runtime/regenerator";
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
import Amplify, { Auth } from "aws-amplify";

var CognitoHandler = function CognitoHandler(appConfig) {
  var _this = this;

  _classCallCheck(this, CognitoHandler);

  this.authProvider = "cognito";
  this.checkIfLoggedIn = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
    var userHandle;
    return _regeneratorRuntime.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            Amplify.configure(_this.authConfig);
            _context.next = 3;
            return Auth.currentAuthenticatedUser();

          case 3:
            userHandle = _context.sent;

            if (userHandle) {
              _this.user = userHandle;
              _this.isLoggedIn = true;
              _this.hasChanged = true;
            }

          case 5:
          case "end":
            return _context.stop();
        }
      }
    }, _callee);
  }));

  this.setUser = function (userHandle) {
    _this.user = userHandle;

    if (userHandle.challengeName === "NEW_PASSWORD_REQUIRED") {
      _this.isChallenged = true;
    } else {
      _this.isLoggedIn = Boolean(userHandle);
      _this.isChallenged = false;
    }

    _this.hasChanged = true;
    _this.error = null;
  };

  this.login = /*#__PURE__*/function () {
    var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(username, password) {
      return _regeneratorRuntime.wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              _context2.next = 2;
              return Auth.signIn(username, password).then(function (user) {
                _this.setUser(user);
              }).catch(function (err) {
                _this.handleCognitoError(err);
              });

            case 2:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2);
    }));

    return function (_x, _x2) {
      return _ref2.apply(this, arguments);
    };
  }();

  this.logout = function () {
    _this.user = null;
    _this.error = null;
    _this.isLoggedIn = false;
    _this.isChallenged = false;
    _this.hasChanged = true;
    Auth.signOut();
  };

  this.completeSignUp = /*#__PURE__*/function () {
    var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(password, requiredAttributesDict) {
      return _regeneratorRuntime.wrap(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              Auth.completeNewPassword(_this.user, // the Cognito User Object
              password, // the new password
              requiredAttributesDict).then(function (user) {
                _this.setUser(user);
              }).catch(function (err) {
                _this.handleCognitoError(err);
              });

            case 1:
            case "end":
              return _context3.stop();
          }
        }
      }, _callee3);
    }));

    return function (_x3, _x4) {
      return _ref3.apply(this, arguments);
    };
  }();

  this.getState = function () {
    return {
      user: _this.user,
      isLoggedIn: _this.isLoggedIn,
      authConfig: _this.authConfig,
      isChallenged: _this.isChallenged,
      error: _this.error
    };
  };

  this.handleCognitoError = function (err) {
    if (err.code === "UserNotConfirmedException") {
      console.log("Must confirm the account");
      _this.error = err.code; // The error happens if the user didn't finish the confirmation step when signing up
      // In this case you need to resend the code and confirm the user
      // About how to resend the code and confirm the user, please check the signUp part
    } else if (err.code === "PasswordResetRequiredException") {
      console.log("Password has been reset");
      _this.error = err.code; // The error happens when the password is reset in the Cognito console
      // In this case you need to call forgotPassword to reset the password
      // Please check the Forgot Password part.
    } else if (err.code === "NotAuthorizedException") {
      console.log("Bad password message");
      _this.error = err.code; //setState({ ...state, notAuthorizedException: true, password: "" })
      // The error happens when the incorrect password is provided
    } else if (err.code === "UserNotFoundException") {
      _this.error = err.code;
      console.log("User not found message"); // The error happens when the supplied username/username does not exist in the Cognito user pool
    } else if (err.code === "InvalidPasswordException") {
      _this.error = err.code;
      console.log("Invalid password"); // The error happens when the password is not conforming to Cognito Policy
    } else {
      _this.error = err.code;
      console.log("Error that we do not handle for:");
      console.log(err.code);
    }

    _this.errorOccured = true;
  };

  this.passwordValidator = function (password) {
    var validations = {
      isValid: true,
      validationsMessages: []
    };

    if (_this.authConfig.Auth.requireLowercase) {
      var lowercaseReg = new RegExp(/.*[a-z].*/);

      if (lowercaseReg.test(password)) {
        validations.validationsMessages.push({
          isValid: true,
          key: "requireLowercase",
          message: "Password must contain a lower case letter"
        });
      } else {
        validations.isValid = false;
        validations.validationsMessages.push({
          isValid: false,
          key: "requireLowercase",
          message: "Password must contain a lower case letter"
        });
      }
    }

    if (_this.authConfig.Auth.requireUppercase) {
      var uppercaseReg = new RegExp(/.*[A-Z].*/);

      if (uppercaseReg.test(password)) {
        validations.validationsMessages.push({
          isValid: true,
          key: "requireUppercase",
          message: "Password must contain an upper case letter"
        });
      } else {
        validations.isValid = false;
        validations.validationsMessages.push({
          isValid: false,
          key: "requireUppercase",
          message: "Password must contain an upper case letter"
        });
      }
    }

    if (_this.authConfig.Auth.requireNumbers) {
      var numbersReg = new RegExp(/.*[0-9].*/);

      if (numbersReg.test(password)) {
        validations.validationsMessages.push({
          isValid: true,
          key: "requireNumbers",
          message: "Password must contain a number"
        });
      } else {
        validations.isValid = false;
        validations.validationsMessages.push({
          isValid: false,
          key: "requireNumbers",
          message: "Password must contain a number"
        });
      }
    }

    if (_this.authConfig.Auth.requireSymbols) {
      var symbolsReg = new RegExp(/.*[=+\-^$*.[\]{}()?"!@#%&/\\,><':;|_~`].*/);

      if (symbolsReg.test(password)) {
        validations.validationsMessages.push({
          isValid: true,
          key: "requireSymbols",
          message: "Password must contain a special character"
        });
      } else {
        validations.isValid = false;
        validations.validationsMessages.push({
          isValid: false,
          key: "requireSymbols",
          message: "Password must contain a special character"
        });
      }
    }

    if (Boolean(_this.authConfig.Auth.minimumLength)) {
      if (password.length >= parseInt(_this.authConfig.Auth.minimumLength)) {
        validations.validationsMessages.push({
          isValid: true,
          key: "minimumLength",
          message: "Password must contain at least ".concat(_this.authConfig.Auth.minimumLength, " characters")
        });
      } else {
        validations.isValid = false;
        validations.validationsMessages.push({
          isValid: false,
          key: "minimumLength",
          message: "Password must contain at least ".concat(_this.authConfig.Auth.minimumLength, " characters")
        });
      }

      if (password.length > 99) {
        validations.isValid = false;
        validations.validationsMessages.push({
          isValid: false,
          key: "maximum",
          message: "Password must not contain more than 99 characters"
        });
      }
    }

    return validations;
  };

  this.authConfig = {
    Auth: {
      identityPoolId: appConfig["auth.cognito.identityPoolId"],
      region: appConfig["auth.cognito.region"],
      userPoolId: appConfig["auth.cognito.userPoolId"],
      userPoolWebClientId: appConfig["auth.cognito.userPoolWebClientId"],
      mandatorySignIn: true,
      authenticationFlowType: "USER_PASSWORD_AUTH",
      minimumLength: appConfig["auth.cognito.password.minimumLength"],
      requireNumbers: appConfig["auth.cognito.password.requireNumbers"],
      requireSymbols: appConfig["auth.cognito.password.requireSymbols"],
      requireUppercase: appConfig["auth.cognito.password.requireUppercase"],
      requireLowercase: appConfig["auth.cognito.password.requireLowercase"]
    },
    Storage: {
      AWSS3: {
        bucket: appConfig["auth.cognito.storage.awsS3.bucket"],
        region: appConfig["auth.cognito.storage.awsS3.region"]
      }
    }
  };
  this.isLoggedIn = false;
  this.isChallenged = false;
  this.checkIfLoggedIn();
};

export default CognitoHandler;