const { resolve } = require('path')
const { createReadStream } = require('fs')
const { stat } = require('fs').promises
const Client = require('./Client')
const { progressBar } = require('../progress')
const { getCorelliumApi } = require('../corellium-api')

/**
 * @typedef {object} AppsResult
 * @property {Array<{object}>} apps
 */

/**
 * Agent class
 */
class AgentCLI extends Client {
  agentBasePath = () => `v1/instances/${this.instance}/agent/v1`

  ready = async () => await this._fetch('GET', `${this.agentBasePath()}/app/ready/`, {})

  /**
   * List files on device
   * @returns {Promise<Array<{object}>>}
   */
  listFiles = async () => {
    const response = (await this._fetch('GET', `${this.agentBasePath()}/file/device/`, {}))
    // Trim whitespace from file names
    return response.entries.map(f => { return { ...f, name: f.name.trim() } })
  }

  /**
   * List apps on device
   * @returns {Promise<Array<{apps: Array<{object}>}>>}
   */
  listApps = async (options) => {
    const { loadIcons } = options
    const response = (await this._fetch('GET', `${this.agentBasePath()}/app/apps?loadIcons=${loadIcons ? 1 : 0}`, {}))
    return response ? response.apps : []
  }

  installApp = async (app) => {
    // get app info
    const filePath = resolve(app)
    const { size: fileSize } = await stat(filePath)

    // get agent for app install
    const corellium = await getCorelliumApi()
    const instance = await corellium.getInstance(this.instance)
    const agent = await instance.agent()

    // configure upload bar for user
    const uploadBar = progressBar()
    uploadBar.start(fileSize, 0)
    const uploadProgress = (progress) => {
      uploadBar.update(progress)
      if (progress >= fileSize) {
        uploadBar.stop()
      }
    }

    // upload and install app
    await agent.installFile(createReadStream(filePath), () => {}, uploadProgress)

    // cleanup
    await agent.disconnect()
  };
}

module.exports = AgentCLI
