const Connector = require("./Connector")
const config = require('../../config.json')
const md5 = require('md5')
const axios = require('axios')
// [ "ecityruf", "123456789" ]
class eMessageAlertManagerConnectorBase extends Connector {
  constructor (amqpConnMngr) {
    super(amqpConnMngr)
    this.name = "emessage"
    this.defaultServiceName = ""
    this.duplexCapable = true
    this.supportBOSkrypt = true
  }
  async transmitMessage(msg, params) {
    const UUID = this.name+':'+md5(JSON.stringify([this.name,...params]))
    const target = params[0]

    const overwriteIdentifier = target.indexOf('#') > -1
    //if (target.split('#').length !== 2) throw 'No valid eMessage Parameter <serviceName#identifier>'
    const serviceName = overwriteIdentifier ? target.split('#')[ 0 ] : this.defaultServiceName,
          identifier = overwriteIdentifier ? target.split('#')[ 1 ] : target

    const $device = msg.routingParams.device
    let payloadBuffer = Buffer.from(msg.payload)
    const boskryptSupport = require("../DeviceRegistry").Devices[ $device ].supportBOSkrypt || false
    if (boskryptSupport && !!config.boskrypt && config.boskrypt.enabled) {
        //payloadBuffer
        const keyTable = config.boskrypt.keys
        const FunkrufNummer = "em-"+identifier
        if (!!keyTable[ FunkrufNummer ]) {
            payloadBuffer = Buffer.from(boskrypt.encrypt(payloadBuffer, keyTable[ FunkrufNummer ], 0))
        }
    }


    let jwtToken = '', msgTrackID = ''
    // login
    axios.post('https://api.emessage.de/auth/login', {
      username: config.connectors.emessage.username,
      password: config.connectors.emessage.password
    })
    .then((loginReq) => { // extract jwt
      if (loginReq.data.apiStatusCode != 200) { throw loginReq }
      jwtToken = loginReq.data.data.jwt
      return jwtToken
    })
    .then(() => { // send Message Request
      return axios.post('https://api.emessage.de/rs/eSendMessages', {
        messageText: payloadBuffer.toString('ascii'),
        recipients: [{ serviceName, identifier }]
      }, {
        headers: {
          'Authorization': `Bearer ${ jwtToken }`
        }
      })
    })
    .then((sndMessageReq) => { // extract tracking ID from response
      if (sndMessageReq.data.apiStatusCode != 200) { throw sndMessageReq }
      this.connectorRegistry.reportState(msg, UUID, 'routed') // since we queued the message, we shall mark it was routed
      msgTrackID = sndMessageReq.data.data.trackingId
      console.log('TRACKING ID', msgTrackID)
      return msgTrackID
    })
    /*.then((_) => { // extract tracking ID from response
      this.connectorRegistry.reportState(msg, UUID, 'routed')
      msgTrackID = '04872f70-9029-11ec-b877-e5935093b691'
      return msgTrackID
    })*/
    .then(async () => { // check for response til duplexTimeout
      const delaySeconds = (timeout) => new Promise(r=>setTimeout(r, timeout * 1e3))
      const checkDelivery = async () => {
        try {
          let res = await axios.get('https://api.emessage.de/rs/eGetMessages/External/' + msgTrackID, {
            headers: {
              'Authorization': `Bearer ${ jwtToken }`
            }
          })
          let deliveryState = res.data.data.recipients[ 0 ].status[ 0 ].answer
          if (deliveryState == 'INTRANSIT') this.connectorRegistry.reportState(msg, UUID, 'transit')
          if (deliveryState == 'SENT') this.connectorRegistry.reportState(msg, UUID, 'sent')
          if (deliveryState == 'RECEIVED' || +deliveryState > 0) {
            this.connectorRegistry.reportDelivered(msg, UUID)
            return true
          }
          console.log(JSON.stringify(res.data.data))
          //this.connectorRegistry.reportState(msg, UUID, deliveryState)

          return false
          //if (res.data.data.recipients.filter(rec=>))
        } catch (e) {
          throw e
        }
      }
      const checkResponse = async () => {
        try {
          let res = await axios.get('https://api.emessage.de/rs/eGetMessages/External/' + msgTrackID, {
            headers: {
              'Authorization': `Bearer ${ jwtToken }`
            }
          })
          let status = res.data.data.recipients[ 0 ].status[ 0 ]
          //if (deliveryState == 'INTRANSIT') this.connectorRegistry.reportState(msg, UUID, 'transit')
          /*if (deliveryState == 'RECEIVED' || +deliveryState > 0) {
            this.connectorRegistry.reportDelivered(msg, UUID)
            return true
          }*/
          if (+status.answerNo == 1 && +status.answer > -1 ) {
            //this.connectorRegistry.response(msg, status.answer)
            require('../MessageManager').markMessageRead(msg.id)
            require('../MessageManager').respondToMessage(msg.id, +status.answer)
            return true
          }

          return false
          //if (res.data.data.recipients.filter(rec=>))
        } catch (e) {
          throw e
        }
      }
      
      const deliveryProcess = new Promise(async (res, rej) => {
        const { startInterval, duplexTimeout } = config.connectors.emessage
        let nextDelay = startInterval + 0
        do {
          let resultCheck = await checkDelivery()
          if (resultCheck == true) return res()
          await delaySeconds(nextDelay)
          nextDelay *= 2 // wait 2x longer than before
        } while (nextDelay <= duplexTimeout)
        return rej()
      })
      const responseProcess = new Promise(async (res, rej) => {
        const { startInterval, responseTimeout } = config.connectors.emessage
        let nextDelay = startInterval + 0
        do {
          let resultCheck = await checkResponse()
          if (resultCheck == true) return res()
          await delaySeconds(nextDelay)
          nextDelay *= 2 // wait 2x longer than before
        } while (nextDelay <= responseTimeout)
        return rej()
      })
      return Promise.race([
        new Promise((res, rej) => { // exit pattern after duplexTimeout
          setTimeout(rej, config.connectors.emessage.duplexTimeout * 1e3)
        }),
        deliveryProcess.then(responseProcess)
      ])
    })
    .catch((err) => {
      console.error(err)
      this.connectorRegistry.reportFail(msg, UUID)
      return false
    })

  }
}


class eMessageAlertManagerConnectorCityruf extends eMessageAlertManagerConnectorBase {
  constructor (amqpConnMngr) {
    super(amqpConnMngr)
    this.name = "em-a-cityruf"
    this.defaultServiceName = "eCityruf"
    this.duplexCapable = true
    this.supportBOSkrypt = true
  }
}
class eMessageAlertManagerConnectorTwoWays extends eMessageAlertManagerConnectorBase {
  constructor (amqpConnMngr) {
    super(amqpConnMngr)
    this.name = "em-a-twoways"
    this.defaultServiceName = "2wayS"
    this.duplexCapable = true
    this.supportBOSkrypt = true
  }
}



module.exports = {
  eMessageAlertManagerConnectorBase,
  eMessageAlertManagerConnectorCityruf,
  eMessageAlertManagerConnectorTwoWays
}