module.exports = api => {
  const CONFIG = 'org.vue.pwa'

  // Config file
  api.describeConfig({
    id: CONFIG,
    name: 'PWA',
    description: 'org.vue.pwa.config.pwa.description',
    link: 'https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa#configuration',
    files: {
      vue: {
        js: ['vue.config.js']
      },
      manifest: {
        json: ['public/manifest.json']
      }
    },
    onRead: ({ data }) => {
      // Dirty hack here: only in onRead can we delete files from the original data.
      // Remove (or, don't create the file) manifest.json if no actual content in it.
      if (!data.manifest || !Object.keys(data.manifest).length) {
        delete data.manifest
      }

      return {
        prompts: [
          {
            name: 'workboxPluginMode',
            type: 'list',
            message: 'org.vue.pwa.config.pwa.workboxPluginMode.message',
            description: 'org.vue.pwa.config.pwa.workboxPluginMode.description',
            link: 'https://developers.google.com/web/tools/workbox/modules/workbox-webpack-plugin#which_plugin_to_use',
            default: 'GenerateSW',
            value: data.vue && data.vue.pwa && data.vue.pwa.workboxPluginMode,
            choices: [
              {
                name: 'GenerateSW',
                value: 'GenerateSW'
              },
              {
                name: 'InjectManifest',
                value: 'InjectManifest'
              }
            ]
          },
          {
            name: 'name',
            type: 'input',
            message: 'org.vue.pwa.config.pwa.name.message',
            description: 'org.vue.pwa.config.pwa.name.description',
            value: data.vue && data.vue.pwa && data.vue.pwa.name
          },
          {
            name: 'themeColor',
            type: 'color',
            message: 'org.vue.pwa.config.pwa.themeColor.message',
            description: 'org.vue.pwa.config.pwa.themeColor.description',
            default: '#4DBA87',
            value: data.vue && data.vue.pwa && data.vue.pwa.themeColor
          },
          {
            name: 'backgroundColor',
            type: 'color',
            message: 'org.vue.pwa.config.pwa.backgroundColor.message',
            description: 'org.vue.pwa.config.pwa.backgroundColor.description',
            default: '#000000',
            value:
              (data.vue &&
                data.vue.pwa &&
                data.vue.pwa.manifestOptions &&
                data.vue.pwa.manifestOptions.background_color) ||
              (data.manifest && data.manifest.background_color),
            skipSave: true
          },
          {
            name: 'msTileColor',
            type: 'color',
            message: 'org.vue.pwa.config.pwa.msTileColor.message',
            description: 'org.vue.pwa.config.pwa.msTileColor.description',
            default: '#000000',
            value: data.vue && data.vue.pwa && data.vue.pwa.msTileColor
          },
          {
            name: 'appleMobileWebAppStatusBarStyle',
            type: 'input',
            message: 'org.vue.pwa.config.pwa.appleMobileWebAppStatusBarStyle.message',
            description: 'org.vue.pwa.config.pwa.appleMobileWebAppStatusBarStyle.description',
            default: 'default',
            value: data.vue && data.vue.pwa && data.vue.pwa.appleMobileWebAppStatusBarStyle
          },
          {
            name: 'manifestCrossorigin',
            type: 'list',
            message: 'org.vue.pwa.config.pwa.manifestCrossorigin.message',
            description: 'org.vue.pwa.config.pwa.manifestCrossorigin.description',
            default: null,
            value: data.vue && data.vue.pwa && data.vue.pwa.manifestCrossorigin,
            choices: [
              {
                name: 'none',
                value: null
              },
              {
                name: 'anonymous',
                value: 'anonymous'
              },
              {
                name: 'use-credentials',
                value: 'use-credentials'
              }
            ]
          }
        ]
      }
    },
    onWrite: async ({ api: onWriteApi, data, prompts }) => {
      const result = {}
      for (const prompt of prompts.filter(p => !p.raw.skipSave)) {
        result[`pwa.${prompt.id}`] = await onWriteApi.getAnswer(prompt.id)
      }

      const backgroundColor = await onWriteApi.getAnswer('backgroundColor')
      if (!data.manifest && backgroundColor) {
        result['pwa.manifestOptions.background_color'] = backgroundColor
      }

      onWriteApi.setData('vue', result)

      // Update app manifest (only when there's a manifest.json file,
      // otherwise it will be inferred from options in vue.config.js)
      if (data.manifest) {
        const name = result.name
        if (name) {
          onWriteApi.setData('manifest', {
            name,
            short_name: name
          })
        }

        const themeColor = result.themeColor
        if (themeColor) {
          onWriteApi.setData('manifest', {
            theme_color: themeColor
          })
        }

        if (backgroundColor) {
          onWriteApi.setData('manifest', {
            background_color: backgroundColor
          })
        }
      }
    }
  })

  const OPEN_VUE = 'org.vue.pwa.open-vue'
  const OPEN_MANIFEST = 'org.vue.pwa.open-manifest'

  api.onViewOpen(({ view }) => {
    if (view.id !== 'vue-project-configurations') {
      removeSuggestions()
    }
  })

  api.onConfigRead(({ config }) => {
    if (config.id === CONFIG) {
      if (config.foundFiles.vue) {
        api.addSuggestion({
          id: OPEN_VUE,
          type: 'action',
          label: 'org.vue.pwa.suggestions.open-vue.label',
          handler () {
            const file = config.foundFiles.vue.path
            const { launch } = require('@vue/cli-shared-utils')
            launch(file)
            return {
              keep: true
            }
          }
        })
      } else {
        api.removeSuggestion(OPEN_VUE)
      }
      if (config.foundFiles.manifest) {
        api.addSuggestion({
          id: OPEN_MANIFEST,
          type: 'action',
          label: 'org.vue.pwa.suggestions.open-manifest.label',
          handler () {
            const file = config.foundFiles.manifest.path
            const { launch } = require('@vue/cli-shared-utils')
            launch(file)
            return {
              keep: true
            }
          }
        })
      } else {
        api.removeSuggestion(OPEN_MANIFEST)
      }
    } else {
      removeSuggestions()
    }
  })

  function removeSuggestions () {
    [OPEN_VUE, OPEN_MANIFEST].forEach(id => api.removeSuggestion(id))
  }
}
