const fs = require('fs')
const path = require('path')
const request = require('request-promise-native')

module.exports = async function (packageRepoName, apiToken, version, artifacts) {
  for (let artifact of artifacts) {
    let fileExt = path.extname(artifact)
    switch (fileExt) {
      case '.deb':
        await uploadDebPackage(version, artifact)
        break
      case '.rpm':
        await uploadRpmPackage(version, artifact)
        break
      default:
        continue
    }
  }

  async function uploadDebPackage (version, filePath) {
    // NOTE: Not sure if distro IDs update over time, might need
    // to query the following endpoint dynamically to find the right IDs:
    //
    // https://{apiToken}:@packagecloud.io/api/v1/distributions.json
    await uploadPackage({
      version,
      filePath,
      type: 'deb',
      arch: 'amd64',
      fileName: 'atom-amd64.deb',
      distroId: 35 /* Any .deb distribution */,
      distroName: 'any',
      distroVersion: 'any'
    })
  }

  async function uploadRpmPackage (version, filePath) {
    await uploadPackage({
      version,
      filePath,
      type: 'rpm',
      arch: 'x86_64',
      fileName: 'atom.x86_64.rpm',
      distroId: 140 /* Enterprise Linux 7 */,
      distroName: 'el',
      distroVersion: '7'
    })
  }

  async function uploadPackage (packageDetails) {
    // Infer the package suffix from the version
    if (/-beta\d+/.test(packageDetails.version)) {
      packageDetails.releaseSuffix = '-beta'
    } else if (/-nightly\d+/.test(packageDetails.version)) {
      packageDetails.releaseSuffix = '-nightly'
    }

    await removePackageIfExists(packageDetails)
    await uploadToPackageCloud(packageDetails)
  }

  function uploadToPackageCloud (packageDetails) {
    return new Promise(async (resolve, reject) => {
      console.log(`Uploading ${packageDetails.fileName} to https://packagecloud.io/AtomEditor/${packageRepoName}`)
      var uploadOptions = {
        url: `https://${apiToken}:@packagecloud.io/api/v1/repos/AtomEditor/${packageRepoName}/packages.json`,
        formData: {
          'package[distro_version_id]': packageDetails.distroId,
          'package[package_file]': fs.createReadStream(packageDetails.filePath)
        }
      }

      request.post(uploadOptions, (error, uploadResponse, body) => {
        if (error || uploadResponse.statusCode !== 201) {
          console.log(`Error while uploading '${packageDetails.fileName}' v${packageDetails.version}: ${uploadResponse}`)
          reject(uploadResponse)
        } else {
          console.log(`Successfully uploaded ${packageDetails.fileName}!`)
          resolve(uploadResponse)
        }
      })
    })
  }

  async function removePackageIfExists ({ version, type, arch, fileName, distroName, distroVersion, releaseSuffix }) {
    // RPM URI paths have an extra '/0.1' thrown in
    let versionJsonPath =
      type === 'rpm'
        ? `${version.replace('-', '.')}/0.1`
        : version

    try {
      const existingPackageDetails =
        await request({
          uri: `https://${apiToken}:@packagecloud.io/api/v1/repos/AtomEditor/${packageRepoName}/package/${type}/${distroName}/${distroVersion}/atom${releaseSuffix || ''}/${arch}/${versionJsonPath}.json`,
          method: 'get',
          json: true
        })

      if (existingPackageDetails && existingPackageDetails.destroy_url) {
        console.log(`Deleting pre-existing package ${fileName} in ${packageRepoName}`)
        await request({
          uri: `https://${apiToken}:@packagecloud.io/${existingPackageDetails.destroy_url}`,
          method: 'delete'
        })
      }
    } catch (err) {
      if (err.statusCode !== 404) {
        console.log(`Error while checking for existing '${fileName}' v${version}:\n\n`, err)
      }
    }
  }
}
