//------------------------------------------------------------------------------------
//npm install --save axios dotenv crypto-js
const axios = require("axios");
const CryptoJS = require("crypto-js");
require('dotenv').config()

//------------------------------------------------------------------------------------
/*
BEFORE RUNNING THIS EXAMPLE: 

* Set AMPLIFI_BASE_URL and SERVER_SECRET in an .env file. (Speak to a support 
representative to be issued client credentials and URL after receiving access to the 
sandbox.)

* Set deviceTag using value obtained from onboarding a prospect.

*/
const AMPLIFI_BASE_URL = process.env.AMPLIFI_BASE_URL;
const SERVER_SECRET = process.env.SERVER_SECRET; //obtained when onboarding prospect

const mobileType = "android_v1";
const mobileType2 = "ios_v1";
const deviceTag = "my_deviceTag1713"; //use same deviceTag from onboarding prospect
const halfRef = `some1RANDOM2string${(new Date() / 1).toString()}`;
const dtsValueString = (new Date()).valueOf().toString();
let cryptotext = CryptoJS.AES.encrypt(deviceTag + dtsValueString, SERVER_SECRET).toString();

const credentialsTestChannel = {
  channel: "test",
  deviceTag,
  deviceData: {
    "platform": "test"
  }
};

const credentialsAndroidChannel = {
  "channel": mobileType,
  "dtsValueString": dtsValueString,
  "deviceTag": deviceTag,
  "socket": {
    halfRef: halfRef
  },
  "cryptotext": cryptotext
};

const credentialsIOSChannel = {
  "channel": mobileType2,
  "dtsValueString": dtsValueString,
  "deviceTag": deviceTag,
  "socket": {
    halfRef: halfRef
  },
  "cryptotext": cryptotext
};

const credentialsBrowserChannel = {
  "channel": "browser",
  "deviceId": deviceTag
};



//------------------------------------------------------------------------------------
//Get Authorization Token
/*
All other requests must have a valid authorization token in the request headers, 
so your first request in any workflow should be to /token in order to receive 
an authorization token. A valid token should be included in the headers of all 
subsequent requests.

*/
async function getAuthToken(credentials) {
  const data = credentials;
  const config = {
    method: 'PUT',
    url: `${AMPLIFI_BASE_URL}/token`,
    headers: {
      'Content-Type': "application/json"
    },
    data
  };

  let result;
  try {
    result = await axios.request(config);
    if (result.status === 200) {
      return Promise.resolve(result.data);
    }
  } catch (err) {
    console.log({
      errCode: err.code,
      responseStatus: err.response && err.response.status,
      data: err.response && JSON.stringify(err.response.data)
    });
  }
}



//------------------------------------------------------------------------------------
//Connect Web-Socket
/*
To enable efficient 2-way communication between the prospect and the server-side
processes, we will first request authorization of a websocket connection. The halfRef
value will be a long string used to establish the connection to the device specified
by the deviceTag.

*/
async function connectSocket(authToken, halfRef, deviceTag) {
  const data = {
    halfRef,
    deviceTag
  };
  const config = {
    method: 'POST',
    url: `${AMPLIFI_BASE_URL}/prospect/connectsocket`,
    headers: {
      'Content-Type': "application/json",
      'token': authToken //previously obtained authorization token is required
    },
    data
  };

  let result;
  try {
    result = await axios.request(config);

    if (result.status === 200) {
      return Promise.resolve(result.data);
    }
  } catch (err) {
    console.log({
      errCode: err.code,
      responseStatus: err.response && err.response.status,
      data: err.response && JSON.stringify(err.response.data)
    });
  }
}



//------------------------------------------------------------------------------------
//Run the walkthrough
async function ampliFiAuthWalkthrough() {

  //Get Authorization Token credentialsTestChannel
  console.log(`Start /token example credentialsTestChannel.\n`);
  const authObjectTest = await getAuthToken(credentialsTestChannel);
  let authTokenTest = undefined;

  if (authObjectTest) {
    console.log(`Successfully obtained test user authorization: ${JSON.stringify(authObjectTest)}\n`);
    authTokenTest = authObjectTest.token;
    console.log(`Authorization token: ${authTokenTest}\n`);
  } else {
    console.log(`Error getting Test authorization token\n`)
  }
  console.log(`End /token example credentialsTestChannel.\n`);


  //Connect Websocket
  console.log(`Start /prospect/connectsocket example.\n`);
  let webSocketResult;
  if (authObjectTest) {
    webSocketResult = await connectSocket(authObjectTest, halfRef, deviceTag);
  } else {
    console.log(`Authorization token is required.\n`)
  }
  if (webSocketResult) {
    console.log(`Successfully connected web-socket: ${JSON.stringify(webSocketResult)}\n`);
  }
  console.log(`End /prospect/connectsocket example.\n`);


  //Get Authorization Token credentialsAndroidChannel
  console.log(`Start /token example credentialsAndroidChannel.\n`);
  const authObjectAndroid = await getAuthToken(credentialsAndroidChannel);
  let authTokenAndroid = undefined;

  if (authObjectAndroid) {
    console.log(`Successfully obtained android user authorization: ${JSON.stringify(authObjectAndroid)}\n`);
    authTokenAndroid = authObjectAndroid.token;
    console.log(`Authorization token: ${authTokenAndroid}\n`);
  } else {
    console.log(`Error getting Android authorization token\n`)
  }
  console.log(`End /token example credentialsAndroidChannel.\n`);



  //Get Authorization Token credentialsBrowserChannel
  console.log(`Start /token example credentialsBrowserChannel.\n`);
  const authObjectBrowser = await getAuthToken(credentialsBrowserChannel);
  let authTokenBrowser = undefined;

  if (authObjectBrowser) {
    console.log(`Successfully obtained browser user authorization: ${JSON.stringify(authObjectBrowser)}\n`);
    authTokenBrowser = authObjectBrowser.token;
    console.log(`Authorization token: ${authTokenBrowser}\n`);
  } else {
    console.log(`Error getting Browser authorization token\n`)
  }
  console.log(`End /token example credentialsBrowserChannel.\n`);


  //Get Authorization Token credentialsIOSChannel
  console.log(`Start /token example credentialsIOSChannel.\n`);
  const authObjectIOS = await getAuthToken(credentialsIOSChannel);
  let authTokenIOS = undefined;

  if (authObjectIOS) {
    console.log(`Successfully obtained iOS user authorization: ${JSON.stringify(authObjectIOS)}\n`);
    authTokenIOS = authObjectIOS.token;
    console.log(`Authorization token: ${authTokenIOS}\n`);
  } else {
    console.log(`Error getting iOS authorization token\n`)
  }
  console.log(`End /token example credentialsIOSChannel.\n`);

}


if (process.env.SERVER_SECRET && process.env.AMPLIFI_BASE_URL) {
  ampliFiAuthWalkthrough();
} else {
  console.log("Before running the walkthrough, set the required .env variables.");
}