text: 'use strict'
  
  const cli = require('heroku-cli-util')
  const co = require('co')
  
  let context
  let heroku
  let app
  let name
  let plan
  let addon
  let service
  
  function noPlanError () {
    throw new Error(`Error: No plan specified.
  You need to specify a plan to move ${cli.color.yellow(name)} to.
  For example: ${cli.color.blue('heroku addons:upgrade heroku-redis:premium-0')}
  
  ${cli.color.cyan('https://devcenter.heroku.com/articles/managing-add-ons')}`)
  }
  
  function handlePlanChangeAPIError (err) {
    const { sortBy } = require('lodash')
  
    if (err.statusCode === 422 && err.body.message && err.body.message.startsWith("Couldn't find either the add-on")) {
      return heroku.get(`/addon-services/${service}/plans`)
        .then((plans) => {
          plans = sortBy(plans, 'price.cents').map((plans) => plans.name)
          throw new Error(`${err.body.message}
  
  Here are the available plans for ${cli.color.yellow(service)}:
  ${plans.join('\n')}
  
  See more plan information with ${cli.color.blue('heroku addons:plans ' + service)}
  
  ${cli.color.cyan('https://devcenter.heroku.com/articles/managing-add-ons')}`)
        })
    }
    throw err
  }
  
  function handleAPIError (err) {
    if (err.statusCode === 422 && err.body.id === 'multiple_matches') {
      let example = err.body.message.split(', ')[2] || 'redis-triangular-1234'
      throw new Error(`${err.body.message}
  
  Multiple add-ons match ${cli.color.yellow(name)}${app ? ' on ' + app : ''}
  It is not clear which add-on's plan you are trying to change.
  
  Specify the add-on name instead of the name of the add-on service.
  For example, instead of: ${cli.color.blue('heroku addons:upgrade ' + context.args.addon + ' ' + (context.args.plan || ''))}
  Run this: ${cli.color.blue('heroku addons:upgrade ' + example + ' ' + name + ':' + plan)}
  ${!app ? 'Alternatively, specify an app to filter by with ' + cli.color.blue('--app') : ''}
  ${cli.color.cyan('https://devcenter.heroku.com/articles/managing-add-ons')}`)
    }
    throw err
  }
  
  function * run (c, h) {
    const resolver = require('../../lib/resolve')
    const util = require('../../lib/util')
  
    context = c
    heroku = h
    app = context.app
    name = context.args.addon
    plan = context.args.plan
  
    // called with just one argument in the form of `heroku addons:upgrade heroku-redis:hobby`
    if (!plan && name.indexOf(':') !== -1) {
      let s = name.split(':')
      name = s[0]
      plan = s[1]
    }
  
    if (!plan) noPlanError()
    // ignore the service part of the plan since we can infer the service based on the add-on
    if (plan.indexOf(':') !== -1) plan = plan.split(':')[1]
  
    // find the add-on to be changed
    addon = yield resolver.addon(h, app, name).catch((e) => handleAPIError(e))
  
    service = addon.addon_service.name
    app = addon.app.name
    plan = `${service}:${plan}`
    yield cli.action(`Changing ${cli.color.magenta(addon.name)} on ${cli.color.cyan(app)} from ${cli.color.blue(addon.plan.name)} to ${cli.color.blue(plan)}`, { success: false }, co(function * () {
      addon = yield heroku.request({
        path: `/apps/${app}/addons/${addon.name}`,
        method: 'PATCH',
        body: { plan: { name: plan } },
        headers: {
          'Accept-Expansion': 'plan',
          'X-Heroku-Legacy-Provider-Messages': 'true'
        }
      }).catch((e) => handlePlanChangeAPIError(e))
      cli.action.done(`done, ${cli.color.green(util.formatPrice(addon.plan.price))}`)
      if (addon.provision_message) cli.log(addon.provision_message)
    }))
  }
  
  let cmd = {
    topic: 'addons',
    description: 'change add-on plan',
    help: `See available plans with \`heroku addons:plans SERVICE\`.
  
  Note that \`heroku addons:upgrade\` and \`heroku addons:downgrade\` are the same.
  Either one can be used to change an add-on plan up or down.
  
  https://devcenter.heroku.com/articles/managing-add-ons`,
    examples: [
      `Upgrade an add-on by service name:
  $ heroku addons:upgrade heroku-redis:premium-2
  
  Upgrade a specific add-on:
  $ heroku addons:upgrade swimming-briskly-123 heroku-redis:premium-2`
    ],
    needsAuth: true,
    wantsApp: true,
    args: [{ name: 'addon' }, { name: 'plan', optional: true }],
    run: cli.command({ preauth: true }, co.wrap(run))
  }
  
  module.exports = [
    Object.assign({ command: 'upgrade' }, cmd),
    Object.assign({ command: 'downgrade' }, cmd)
  ]
  