<template>
  <q-view layout="hbox" id="wrap" layout-spacing="0" v-if="!isLoading">
    <q-view layout="vbox" id="steps" layout-spacing="0">
      <q-view layout="hbox" id="steps__item" :layout-spacing="0" v-for="(step, index) in steps">
        <q-view layout="vbox" :layout-spacing="0" id="steps__item-no">
          <q-view layout="hbox">
            <q-view id="steps__item-no-line--selected" v-if="currentStep === index"></q-view>
            <q-view id="steps__item-no-line--normal" v-else></q-view>
          </q-view>
          <q-label :text="index + 1" alignment='AlignCenter' id="steps__item-no-number--selected"
                   v-if="currentStep === index"></q-label>
          <q-label :text="index + 1" alignment='AlignCenter' id="steps__item-no-number--normal" v-else></q-label>
          <q-view layout="hbox">
            <q-view id="steps__item-no-line--selected" v-if="currentStep === index"></q-view>
            <q-view id="steps__item-no-line--normal" v-else></q-view>
          </q-view>
        </q-view>
        <q-view layout="vbox">
          <q-label :text="step.title" id="steps__item-title"></q-label>
        </q-view>
      </q-view>
    </q-view>
    <q-view layout="vbox" id="steps-body" :layout-spacing="0">
      <q-view layout="vbox" id="step-body__item-0" v-if="currentStep === 0">
        <q-view vertical-size-policy="Expanding"></q-view>
        <q-view layout="vbox" v-if="!isLogin">
          <q-view layout="vbox">
            <q-label :text="`项目[${workspaceFolder.name}]使用了uniCloud，需要进行uniCloud初始化操作。`" id="text-primary-color" alignment='AlignCenter'></q-label>
            <q-label text="检测到您还未登录，请先登录" id="text-primary-color" alignment='AlignCenter'></q-label>
            <q-view layout="hbox">
              <q-button text="登录" @clicked="showLogin" style="min-width: 100px; max-width: 100px;" id="HXButton"></q-button>
            </q-view>
          </q-view>
        </q-view>
        <q-view layout="vbox" v-else-if="!isRealName">
          <q-view layout="vbox">
            <q-label :text="`项目[${workspaceFolder.name}]使用了uniCloud服务，根据国家法律要求，使用云服务需要实名认证`" id="text-primary-color"></q-label>
            <q-view layout="hbox" :layout-spacing="0">
              <q-label text="请先完成" id="text-primary-color"></q-label>
              <q-button text="实名认证" id="text-selected-color" style="border: 0; text-decoration: underline;" @clicked="redirectRealNamePageUrl"></q-button>
              <q-label text="或者使用临时服务空间。" id="text-primary-color"></q-label>
              <q-view horizontal-size-policy="Expanding"></q-view>
            </q-view>
            <q-radio-group layout="vbox">
              <q-radio id='RadioButton' text="已完成实名认证" :checked="isRealNameFinish" :data-value="true" @toggled="readNameRadioGroupChanged"></q-radio>
              <q-radio id='RadioButton' text="先不认证,临时体验" :checked="!isRealNameFinish" v-if="provider === 'aliyun'" :data-value="false" @toggled="readNameRadioGroupChanged"></q-radio>
            </q-radio-group>
            <q-label v-if="provider === 'aliyun'" text="临时服务空间创建后4小时自动销毁，如在临时服务空间销毁之前完成" id="text-second-color"></q-label>
            <q-label v-if="provider === 'aliyun'" text="实名认证，则该服务空间会继续保留。" id="text-second-color"></q-label>
          </q-view>
        </q-view>
        <q-view vertical-size-policy="Expanding"></q-view>
      </q-view>
      <q-view layout="vbox" id="step-body__item-1" v-if="currentStep === 1">
        <q-label id="text-primary-color"
                 :text="`该步骤将为项目[${workspaceFolder.name}]绑定一个服务空间，请在下方列表中选择一个服务<br/>空间进行绑定。后续仍可以通过在项目下的uniCloud目录点击右键重新绑定。`"></q-label>
        <q-view vertical-size-policy="Expanding"></q-view>
        <q-view layout="hbox">
          <q-label text="选择要绑定的服务空间" id="text-primary-color"></q-label>
          <q-view horizontal-size-policy='Expanding'></q-view>
          <q-view layout="hbox">
            <q-view horizontal-size-policy='Expanding'></q-view>
            <q-button id="btn" text="新增" icon='@icon.folder@unicloud_add.png'
                      @clicked="redirectUniCloudConsole"></q-button>
            <q-button id="btn" text="刷新" icon='@icon.folder@unicloud_refresh.png' @clicked="refresh"></q-button>
          </q-view>
        </q-view>
        <q-list-view id="list" currentIndex="-1" @currentRowChanged="currentRowChanged">
          <q-list-item layout="hbox" v-for="space in spaces">
            <q-view layout="hbox">
              <q-radio id='checkBox' :enabled='false' :checked='space.selected'></q-radio>
            </q-view>
            <q-label :text="space.spaceName" id="list__label" :toolTip="space.spaceName"
                     :style="{color: space.selected ? '#4EAB57': '#405E42'}"></q-label>
            <q-view horizontal-size-policy='Expanding'></q-view>
            <q-view layout="hbox" style="min-width: 100px">
              <q-label :text="space.spaceProvider" id="list__label"
                       :style="{color: space.selected ? '#4EAB57': '#405E42'}"></q-label>
            </q-view>
          </q-list-item>
        </q-list-view>
      </q-view>
      <q-view layout="vbox" id="step-body__item-2" v-if="currentStep === 2">
        <q-view vertical-size-policy="Expanding"></q-view>
        <q-view layout="hbox">
          <q-checkbox id="HXCheckBox" text="部署项目下的所有云函数、公共模块及actions" data-field="deployFunctions" @stateChanged="deployItemStateChanged"></q-checkbox>
          <q-button text="查看>>" id="text-selected-color" style="border: 0" data-folder="deployFunctions" @clicked="showFolder"></q-button>
          <q-view horizontal-size-policy="Expanding"></q-view>
        </q-view>
        <q-view layout="hbox">
          <q-checkbox id="HXCheckBox" text="初始化服务空间的数据库" data-field="initDatabase" @stateChanged="deployItemStateChanged"></q-checkbox>
          <q-button text="查看>>" id="text-selected-color" style="border: 0" data-folder="initDatabase" @clicked="showFolder"></q-button>
          <q-view horizontal-size-policy="Expanding"></q-view>
        </q-view>
<!--        <q-label text="包含db_init.json配置的数据项及数据项同名的DB Schema" id="text-second-color"></q-label>-->
<!--        <q-label text="database下的扩展校验函数" id="text-second-color"></q-label>-->
        <q-view vertical-size-policy="Expanding"></q-view>
      </q-view>
      <q-view layout="hbox" id="steps-body__footer">
        <q-label :openExternalLinks="true" text="<a href='https://uniapp.dcloud.io/uniCloud/README' style='color: #4EAB57'>什么是uniCloud?</a>" id="text-selected-color"></q-label>
        <q-view horizontal-size-policy="Expanding"></q-view>
        <q-button id="HXButton" :text="currentStep === 0 || (currentStep === 1 && this.userInfoOk) ? '取消': '上一步'" @clicked="prev"></q-button>
        <q-button id="HXButton" :text="processButtonText" v-if="showProcessButton"></q-button>
        <q-button id="HXButton" :text="currentStep < (steps.length - 1) ? '下一步': '开始部署'" @clicked="next" v-else></q-button>
      </q-view>
    </q-view>
  </q-view>
</template>

<script>

const hx = require('hbuilderx')
const url = require('url')
const fs = require('fs')
const path = require('path')

const providerMap = {
  tcb: '腾讯云',
  aliyun: '阿里云',
  alipay: '支付宝云'
}

export default {
  data () {
    return {
      currentStep: 0,
      currentSpaceId: null,
      isLoading: true,
      isLogin: false,
      isRealName: false,
      isRealNameFinish: true,
      processButtonText: "",
      showProcessButton: false,
      steps: [
        {
          title: '检查用户信息',
          fullTitle: '检查用户信息'
        }, {
          title: '选择服务空间',
          fullTitle: '绑定uniCloud服务空间到项目[{projectName}]'
        }, {
          title: '部署云端资源',
          fullTitle: `部署项目[{projectName}]云端资源到服务空间[{spaceName}]`
        }
      ],
      spaces: [],
      provider: '',
      workspaceFolder: {},
      deployFunctions: false,
      initDatabase: false
    }
  },
  computed: {
    userInfoOk () {
      return this.isLogin && this.isRealName
    }
  },
  watch: {
    currentStep (newValue) {
      if (newValue === 1 && this.spaces.length <= 0) {
        this.$nextTick(() => {
          this.getSpaceServices()
        })
      }

      // 更新 form dialog title
      this.$formDialog.updateForm({
        title: this.buildTitle(this.steps[newValue].fullTitle)
      })
    }
  },
  mounted () {
    this.$nextTick(() => {
      this.startFlowCtrl()
    })
  },
  methods: {
    async startFlowCtrl () {
      this.$formDialog.showLoading({
        maskAt: 'initUniCloudSpaceWizard'
      })

      // 检查用户信息
      await this.checkUserStatus()
      if (this.userInfoOk) {
        this.currentStep = 1
      }
      this.isLoading = false

      await this.updateUi()
      this.$formDialog.hideLoading()
    },
    readNameRadioGroupChanged (e) {
      const {'data-value': value} = e.target
      this.isRealNameFinish = value
    },
    async deployItemStateChanged (e) {
      const {'data-field': field, checked} = e.target

      if (field) {
        this[field] = checked
      }

      await this.updateUi()
    },
    async checkUserStatus () {
      const { isLogin } = await hx.authorize.requestUserInfo()

      this.isLogin = isLogin

      await this.updateUi()

      if (!isLogin) return

      const userInfo = await this.getUserInfo()

      if (userInfo && userInfo.authenticated) {
        this.isRealName = true
        await this.updateUi()
      }
    },
    async getUserInfo () {
      const { email } = await hx.authorize.requestUserInfo()

      const res = await hx.http.request({
        url: `https://ide.liuyingyong.cn/user/info`,
        method: 'get',
        connectionTimeout: 10000,
        readTimeout: 30000,
        params: {
          param: JSON.stringify({
            header: {
              token: '${user.checked.token}'
            },
            body: {
              email
            }
          })
        }
      })

      let response
      try {
        response = JSON.parse(res.data)
      } catch (e) {}
      const code = response && response.header && response.header.result && response.header.result.rspcode
      const data = response && response.body || {}

      if (code === '1001') {
        return data
      }
    },
    async showLogin () {
      hx.authorize.onUserLogin(() => {
        this.$formDialog.hideLoading()

        if (this.isLogin) return

        this.isLogin = true
        this.updateUi()
        this.startFlowCtrl()
      })

      await hx.http.checkLogin({
        forceLogin: true
      })

      this.$nextTick(() => {
        this.$formDialog.showLoading({
          maskAt: 'initUniCloudSpaceWizard'
        })
      })
    },
    async getSpaceServices () {
      this.$formDialog.showLoading({
        maskAt: 'initUniCloudSpaceWizard'
      })

      const res = await hx.http.request({
        url: 'https://ide.liuyingyong.cn/serverless/space/list',
        method: 'post',
        connectionTimeout: 10000,
        readTimeout: 30000,
        serviceOptions: {
          serviceRequest: true,
          body: {
            provider: this.provider,
            appid: this.workspaceFolder.appid
          }
        }
      })

      if (res.service && res.service.code === 1001 && res.service.body.spaces) {
        this.spaces = res.service.body.spaces.filter(item => item.status.toLowerCase() === 'normal').map(item => {
          return {
            spaceId: item.id,
            spaceName: item.name,
            spaceProvider: providerMap[item.provider] + (item.isActor ? '(协作)' : ''),
            openedHosting: item.haveHostingService,
            selected: item.id === this.currentSpaceId,
            provider: item.provider,
            clientSecret: item.clientSecret,
            apiEndpoint: item.apiEndpoint,
            isOwner: item.isOwner,
            isActor: item.isActor
          }
        })
      }

      this.$formDialog.hideLoading()
      this.updateUi()
    },
    async redirectUniCloudConsole () {
      const redirectURL = url.format({
        protocol: 'https',
        hostname: 'dev.dcloud.net.cn',
        pathname: '/auth/dcloud/callback',
        search: new url.URLSearchParams({
          return_url: encodeURIComponent('https://dev.dcloud.net.cn/unicloud/auth?action=openConsole')
        }).toString()
      })

      await hx.env.openExternal(
        url.format({
          protocol: 'https',
          hostname: 'account.dcloud.net.cn',
          pathname: '/oauth2/login',
          search: 'email=${email}&deviceId=${deviceId}&sign=${askSign}&timestamp=${timestamp}&source=hbuilder.win32&client_id=DCLOUD_DEV' + `&sourceversion=${hx.env.appVersion}&redirectURL=${encodeURIComponent(redirectURL)}`,
        })
      )
    },
    async redirectRealNamePageUrl () {
      const redirectURL = url.format({
        protocol: 'https',
        hostname: 'dev.dcloud.net.cn',
        pathname: '/auth/dcloud/callback',
        search: new url.URLSearchParams({
          return_url: encodeURIComponent("https://dev.dcloud.net.cn/user/reg")
        }).toString()
      })

      await hx.env.openExternal(
        url.format({
          protocol: 'https',
          hostname: 'account.dcloud.net.cn',
          pathname: '/oauth2/login',
          search: 'email=${email}&deviceId=${deviceId}&sign=${askSign}&timestamp=${timestamp}&source=hbuilder.win32&client_id=DCLOUD_DEV' + `&sourceversion=${hx.env.appVersion}&redirectURL=${encodeURIComponent(redirectURL)}`,
        })
      )
    },
    async refresh () {
      if (this.spaceLoading) return

      this.spaces = []
      await this.updateUi()

      this.$nextTick(() => {
        this.getSpaceServices()
      })
    },
    currentRowChanged (e) {
      const { currentRow } = e.target

      // 单选
      this.spaces.forEach((item, index) => {
        item.selected = false
      })

      this.spaces[currentRow].selected = !this.spaces[currentRow].selected
      this.updateUi()
    },
    async prev () {
      if (this.currentStep === 0 || (this.currentStep === 1 && this.userInfoOk)) {
        return this.$formDialog.close && this.$formDialog.close()
      }

      await this.stepCtrl(-1)
    },
    async next () {
      if (!this.isLogin) return false
      if (this.currentStep === this.steps.length - 1) {
        this.$formDialog.close && this.$formDialog.close()
        return this.$mitt.emit('startDeploy', {
          space: this.spaces.find(item => item.selected),
          deployFunctions: this.deployFunctions,
          initDatabase: this.initDatabase
        })
      }

      if (this.currentStep === 0) {
        if (this.isRealNameFinish) {
          this.processButtonText = "请稍后..."
          this.showProcessButton = true
          await this.updateUi()

          const userInfo = await this.getUserInfo()
          this.showProcessButton = false
          await this.updateUi()

          if (userInfo && !userInfo.authenticated) {
            return hx.window.showMessageBox({
              type: 'warning',
              title: '',
              text: '请先完成实名认证后在进行下一步',
              buttons: ['确定']
            })
          }

          this.isRealName = userInfo && userInfo.authenticated
          await this.updateUi()
        } else {
          this.processButtonText = "创建中..."
          this.showProcessButton = true
          await this.updateUi()

          const createSuccess = await this.createTempSpace()
          this.showProcessButton = false
          await this.updateUi()

          if (createSuccess && !createSuccess.success) return
        }

        this.currentStep = 1
        this.updateUi()

        return
      }

      if (this.currentStep === 1) {
        const selectedSpace = this.spaces.find(item => item.selected)
        if (!selectedSpace) {
          return await hx.window.showMessageBox({
            type: 'warning',
            title: '',
            text: '请选择一个服务空间',
            buttons: ['确定']
          })
        }
      }

      await this.stepCtrl(1)
    },
    async createTempSpace () {
      if (this.provider !== 'aliyun') {
        return hx.window.showMessageBox({
          type: 'warning',
          title: '',
          text: '仅阿里云支持创建临时服务空间',
          buttons: ['确定']
        })
      }

      const trialInfoRes = await hx.http.request({
        url: 'https://ide.liuyingyong.cn/serverless/space/create-trial',
        method: 'post',
        connectionTimeout: 10000,
        readTimeout: 30000,
        serviceOptions: {
          serviceRequest: true
        }
      })

      if (trialInfoRes.service && trialInfoRes.service.code !== 1001) {
        return hx.window.showMessageBox({
          type: 'warning',
          title: '',
          text: trialInfoRes.service.description || '创建临时服务空间失败',
          buttons: ['确定']
        })
      }

      if (trialInfoRes.service.body && trialInfoRes.service.body.trialInfo) {
        const { isCanTrial, isAlreadyTrial, trialSpace } = trialInfoRes.service.body.trialInfo

        if (!isCanTrial) {
          return hx.window.showMessageBox({
            type: 'warning',
            title: '',
            text: '您暂时不可以创建临时空间',
            buttons: ['确定']
          })
        }

        if (isAlreadyTrial && trialSpace.expireTs < (Date.now() / 1000)) {
          return hx.window.showMessageBox({
            type: 'warning',
            title: '',
            text: `您创建的临时空间已过期，不可以继续创建！`,
            buttons: ['确定']
          })
        }
      }

      const res = await hx.http.request({
        url: 'https://ide.liuyingyong.cn/serverless/space/create-trial',
        method: 'post',
        connectionTimeout: 10000,
        readTimeout: 30000,
        serviceOptions: {
          serviceRequest: true
        }
      })

      if (res.service && res.service.code !== 1001) {
        return hx.window.showMessageBox({
          type: 'warning',
          title: '',
          text: res.service.description || '创建临时服务空间失败',
          buttons: ['确定']
        })
      }

      hx.window.showMessageBox({
        type: 'warning',
        title: '',
        text: '临时服务空间正在创建中, 预计3-5分钟后创建完成，您可以在uniCloud控制台查看创建进度。',
        buttons: ['确定']
      })

      return {
        success: true
      }
    },
    async stepCtrl (step) {
      const newStep = this.currentStep + step
      if (newStep >= 0 && newStep < this.steps.length) {
        this.currentStep = newStep
        await this.updateUi()
      }
    },
    buildTitle (title) {
      const space = this.spaces.find(space => space.selected)
      const params = {
        projectName: this.workspaceFolder.name,
        spaceName: space && space.spaceName
      }

      return title.replace(/\{(\w+)\}/g, (match, key) => {
        return params[key] || match
      })
    },
    showFolder (e) {
      const {'data-folder': folder} = e.target
      const folderList = {
        'deployFunctions': path.resolve(this.workspaceFolder.uri.fsPath, `uniCloud-${this.provider}`, 'cloudfunctions'),
        'initDatabase': path.resolve(this.workspaceFolder.uri.fsPath, `uniCloud-${this.provider}`, 'database')
      }

      const folderPath = folderList[folder]
      if (folderPath && fs.existsSync(folderPath)) {
        hx.workspace.openTextDocument(folderPath)
      }
    },
  }
}
</script>

<style scoped lang="qss">
* {
  font-size: 12px;
}

#btn {
  border: none;
  color: #4EAB57;
}

#text-primary-color {
  color: #405E42;
}

#text-selected-color {
  color: #4EAB57;
}

#text-second-color {
  color: #ccc;
}

#steps {
  min-width: 125px;
  max-width: 125px;
}

#steps__item {
  padding-left: 10px;
}

#steps__item-no {
  min-width: 16px;
  max-width: 16px;
}

#steps__item-no-line--normal {
  min-width: 2px;
  max-width: 2px;
  background-color: #bde7bd;
}

#steps__item-no-line--selected {
  min-width: 2px;
  max-width: 2px;
  background-color: #4EAB57;
}

#steps__item-no-number--normal {
  max-width: 16px;
  min-width: 16px;
  min-height: 16px;
  max-height: 16px;
  border-radius: 8px;
  background-color: #bde7bd;
  color: #fff;
}

#steps__item-no-number--selected {
  max-width: 16px;
  min-width: 16px;
  min-height: 16px;
  max-height: 16px;
  border-radius: 8px;
  background-color: #4EAB57;
  color: #fff;
}

#steps__item-title {
  margin-left: 5px;
  color: #4EAB57;
}

#steps-body {
  /* background-color: red; */
}

#steps-body__footer {
  margin-top: 10px;
}


#list {
  background: #FFFEFA;
  border: 1px solid darkgray;
}

#list::item {
  padding: 5px 20px;
}

#list::item:selected, #list::item:hover {
  background-color: transparent;
}

#list::item #list__label {
  font-size: 14px;
}

#checkBox::indicator::unchecked {
  image: url("");
}

#checkBox::indicator::checked {
  image: url("@icon.folder@ProjectWizard/template_select.png");
}

#HXButton{
  border:1px solid #009944;
  background: #FAFFFA;
  color: #54AE6C;
  padding: 6px 28px;
  font-size: 12px;
}

#HXButton:hover{
  background: #EDFDED;
  border-color: #009944;
}

#HXButton:pressed{
  background: #E1F0E1;
  border-color: #0D9E4D;
}

#HXButton[visualType="accept"]{
  border:1px solid #009944;
  background: #3AAD4F;
  color: #FFFEFA;
}

#HXButton[visualType="accept"]:hover{
  background: #85CE93;
}

#HXButton[visualType="accept"]:pressed{
  background: #229337;
}

#HXButton[visualType="error"]{
  border:1px solid #DE3F3F;
  background: #FFF9F9;
  color: #D14544;
}

#HXButton[visualType="error"]:hover{
  background: #FEEEEE;
}

#HXButton[visualType="error"]:pressed{
  background: #EECFCF;
}

#HXButton:disabled{
  border:1px solid #DCDCDC;
  background: #F3F3F3;
  color: #B1B1B1;
}

#HXButton HXLoadingWidget:disabled{
  color: #B1B1B1;
}

#HXCheckBox {
  color: #405E42;
}
#HXCheckBox::indicator::unchecked{
  image:url(:/hxui/resource/chbx.png);
}

#HXCheckBox::indicator::unchecked:hover{
  image:url(:/hxui/resource/chbx-hover.png);
}

#HXCheckBox::indicator::checked{
  image:url(:/hxui/resource/chbx-checked.png);
}

#HXCheckBox::indicator::checked:disabled{
  image:url(:/hxui/resource/chbx-checked-disable.png);
}

#HXCheckBox::indicator::unchecked:pressed,
#HXCheckBox::indicator::checked:pressed{
  image:url(:/hxui/resource/chbx-pressed.png);
}

#HXCheckBox::indicator:disabled{
  image:url(:/hxui/resource/chbx.png);
}
</style>
