import * as AWSCognito from 'amazon-cognito-identity-js'
import * as AWSSdk from 'aws-sdk'
import * as Shared from 'placeholder-shared'

const USER_POOL_ID = Shared.Common.USER_POOL_ID;
const APP_CLIENT_ID = Shared.Common.APP_CLIENT_ID;
const IDENTITY_POOL_ID = Shared.Common.IDENTITY_POOL_ID;
const AWS_REGION = Shared.Common.AWS_REGION;
const IDP_URL = Shared.Common.IDP_URL;



export const getUserPool = (): AWSCognito.CognitoUserPool => {
  //the user pool id tells cognito which group of users this is
  //the client id tells cognito which app this is
  //this information is public
  var data = {
    UserPoolId: USER_POOL_ID,
    ClientId: APP_CLIENT_ID,
  };
  return new AWSCognito.CognitoUserPool(data);
}

const getResponseCB = (cb: any)=>{
  return (err: any, data: any) => {
    try {
      if (err) {
        console.error("error on cognitoRequest", err)
        cb(err, null);
      }
      else {
        cb(null, data)
      }
    } catch (err) {
      console.error("uncaught error in cognito callback: ", err);
      console.assert(false)
    }
  }
}



export const doRegister = (userPool: AWSCognito.CognitoUserPool, emailInput: string, passwordInput: string, cb: (err: any, data: any) => void) => {
  var attributeList: any = [];
  var userPool = getUserPool();
  var validator: any = null;

  var responseCB = getResponseCB(cb);
  userPool.signUp(emailInput, passwordInput, attributeList, validator, responseCB);
}

export const doVerify = (userPool: AWSCognito.CognitoUserPool, emailInput: string, confirmInput: string, cb: (err: any, data: any) => void) => {
  var userData = {
    Username: emailInput,
    Pool: userPool
  };

  var cognitoUser = new AWSCognito.CognitoUser(userData);
  var responseCB = getResponseCB(cb);
  cognitoUser.confirmRegistration(confirmInput, true, responseCB);
}

export const doLogin = (userPool: AWSCognito.CognitoUserPool, emailInput: string, passwordInput: string, cb: (err: any, data: any) => void) => {
  //log you out if currently logged in as another user
  var cognitoUser = userPool.getCurrentUser();
  removeLocalStorageIDP()
  if(cognitoUser != null){
    cognitoUser.signOut();
  }
  //This should remove bug where you are logged in as two users
  
  var userData = {
    Username: emailInput,
    Pool: userPool
  };
  var authenticationData = {
    Username: emailInput, // your username here
    Password: passwordInput, // your password here
  };
  var authenticationDetails = new AWSCognito.AuthenticationDetails(authenticationData);

  var cognitoUser = new AWSCognito.CognitoUser(userData);
  var responseCB = getResponseCB(cb);
  cognitoUser.authenticateUser(authenticationDetails, {
    onSuccess: (result) => {
     responseCB(null, 'Successfully logged in!'); 
    },
    onFailure: (err) => {
      responseCB(err, null)
    },
    mfaRequired: (codeDeliveryDetails) => {
      console.assert(false)
      //var verificationCode: any = prompt('Please input verification code' ,'');
      //cognitoUser.sendMFACode(verificationCode, (this as any));
    }
  });
}

export const doReset = (userPool: AWSCognito.CognitoUserPool, resetEmailInput: string, resetCodeInput: string, resetPasswordInput: string, cb: (err: any, data: any) => void) => {
  var userData = {
    Username: resetEmailInput,
    Pool: userPool
  };
  var cognitoUser = new AWSCognito.CognitoUser(userData);
  var responseCB = getResponseCB(cb);
  cognitoUser.confirmPassword(resetCodeInput, resetPasswordInput, {
    onSuccess() {
      responseCB(null, 'Password change confirmed!');
    },
    onFailure(err) {
      responseCB(err, null);
    }
  })
}

export const doForgot = (userPool: AWSCognito.CognitoUserPool, forgotEmailInput: string, cb: (err: any, data: any) => void) => {
  var userData = {
    Username: forgotEmailInput,
    Pool: userPool
  };
  var cognitoUser = new AWSCognito.CognitoUser(userData);
  var responseCB = getResponseCB(cb);
  cognitoUser.forgotPassword({
    onSuccess: (data) => {
      responseCB(null, data);
    },
    onFailure: (err) => {
      responseCB(err, null);
    }
  })
}

export const doRefresh = (cb: (err: any, data: any) => void) => {
  var userPool = getUserPool();
  var cognitoUser = userPool.getCurrentUser();
  if (cognitoUser === null) {
    console.log("unauthenticated")
    cb(null, null);
    return;
  }

  cognitoUser.getSession((err: any, session: any) => {
    if (err) {
        cb(err, null);
        return;
    }
    const id_token = session.getIdToken().getJwtToken();
    AWSSdk.config.credentials = new AWSSdk.CognitoIdentityCredentials({
      IdentityPoolId: IDENTITY_POOL_ID, 
      Logins: {
        [IDP_URL + USER_POOL_ID]: id_token
      }
    }, {
      region: AWS_REGION
    });
    
    var responseCB = getResponseCB(cb);
    
    if(AWSSdk.config.credentials == null){
      console.log("Credentials might be empty yet user is logged in: ", AWSSdk.config.credentials);
    }
    (AWSSdk.config.credentials as any).refresh((err: any) => {
      if(err) {
        responseCB(err, null);
      }
      else {
        cognitoUser.getUserAttributes(function(err2, result) {
					if(err2){
						return responseCB(err2, null)
					}
					//console.log('cognitoUser id token: ', result);
					if(result == null ){
						return responseCB(null, null);
					} else {
            const emailAddr = result.find(attr => attr.getName() == 'email').getValue()
						return responseCB(null, {EmailAddr: emailAddr, id_token: id_token})
					}
				});
      }
    });
  });
}

export const getSsoUser = (accessToken, cb) =>{
  const cognitoidentityserviceprovider = new AWSSdk.CognitoIdentityServiceProvider({region: AWS_REGION});
  const params = {
      AccessToken: accessToken 
  };
  const responseCB = getResponseCB(cb);
  cognitoidentityserviceprovider.getUser(params, responseCB)
}

export const getUserId = (idToken, cb) =>{
  const cognitoidentity = new AWSSdk.CognitoIdentity({region: AWS_REGION});
  const params = {
      IdentityPoolId: IDENTITY_POOL_ID,
      Logins: {
        [IDP_URL + USER_POOL_ID]: idToken
      }
    };
  const responseCB = getResponseCB(cb);
  cognitoidentity.getId(params, responseCB);
}

export const doLogout = (cb: (err: any, data: any) => void) => {
  //localStorage.clear();
  console.log("Local Storage IDPs removed");

  var userPool = getUserPool();
  var cognitoUser = userPool.getCurrentUser();
  removeLocalStorageIDP();
  if (cognitoUser === null) return cb('already logged out', null);
  
 
  
  var responseCB = getResponseCB(cb);
  cognitoUser.signOut();
  responseCB(null, "Logout Successful");
}

export const removeLocalStorageIDP =() =>{
  var query = /^aws\.cognito\.identity.*|^CognitoIdentityServiceProvider.*/
  var i;
  for (i in localStorage) {
    
    if (localStorage.hasOwnProperty(i)) {
      
      if (i.match(query) || (!query && typeof i === 'string')) {
        
        localStorage.removeItem(i)
      }
    }
  }
}

export const goGoogle = () =>{
  window.location.href='https://structure.auth.us-west-2.amazoncognito.com/oauth2/authorize?identity_provider=Google&redirect_uri=https://editor.structure.rest/app/editor&response_type=TOKEN&client_id=mjn020f01m2uvvg38ujrt8gts&scope=aws.cognito.signin.user.admin email openid profile'
}
