// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

import Cookies from 'js-cookie'
import { axios, sourceToken } from '@/utils/request'
import { message, notification } from 'ant-design-vue'
import { vueProps } from '@/vue-app'
import {
  ACCESS_TOKEN
} from '@/store/mutation-types'

const getAPICommandsRegex = /^(get|list|query|find)\w+$/i
const additionalGetAPICommandsList = [
  'isaccountallowedtocreateofferingswithtags',
  'readyforshutdown',
  'cloudianisenabled',
  'quotabalance',
  'quotasummary',
  'quotatarifflist',
  'quotaisenabled',
  'quotastatement',
  'quotaemailtemplatelist',
  'verifyoauthcodeandgetuser'
]

export function getAPI (command, args = {}) {
  args.command = command
  args.response = 'json'

  const sessionkey = vueProps.$localStorage.get(ACCESS_TOKEN) || Cookies.get('sessionkey')
  if (sessionkey) {
    args.sessionkey = sessionkey
  }

  return axios({
    params: {
      ...args
    },
    url: '/',
    method: 'GET'
  })
}

export function postAPI (command, data = {}) {
  const params = new URLSearchParams()
  params.append('command', command)
  params.append('response', 'json')
  if (data) {
    Object.entries(data).forEach(([key, value]) => {
      if (value !== undefined && value !== null) {
        params.append(key, value)
      }
    })
  }

  const sessionkey = vueProps.$localStorage.get(ACCESS_TOKEN) || Cookies.get('sessionkey')
  if (sessionkey) {
    params.append('sessionkey', sessionkey)
  }
  return axios({
    url: '/',
    method: 'POST',
    data: params
  })
}

export function callAPI (command, args = {}) {
  const isGetAPICommand = getAPICommandsRegex.test(command) || additionalGetAPICommandsList.includes(command.toLowerCase())
  const call = isGetAPICommand ? getAPI : postAPI
  return call(command, args)
}

export function login (arg) {
  if (!sourceToken.checkExistSource()) {
    sourceToken.init()
  }

  // Logout before login is called to purge any duplicate sessionkey cookies
  postAPI('logout')

  const params = new URLSearchParams()
  params.append('command', 'login')
  params.append('username', arg.username || arg.email)
  params.append('password', arg.password)
  params.append('domain', arg.domain)
  params.append('response', 'json')
  return axios({
    url: '/',
    method: 'POST',
    data: params,
    headers: {
      'content-type': 'application/x-www-form-urlencoded'
    }
  })
}

export async function logout () {
  const result = await postAPI('logout').finally(() => {
    sourceToken.cancel()
    message.destroy()
    notification.destroy()
  })
  return result
}

export function oauthlogin (arg) {
  if (!sourceToken.checkExistSource()) {
    sourceToken.init()
  }

  // Logout before login is called to purge any duplicate sessionkey cookies
  postAPI('logout')

  const params = new URLSearchParams()
  params.append('command', 'oauthlogin')
  params.append('email', arg.email)
  params.append('secretcode', arg.secretcode)
  params.append('provider', arg.provider)
  params.append('domain', arg.domain)
  params.append('response', 'json')
  return axios({
    url: '/',
    method: 'post',
    data: params,
    headers: {
      'content-type': 'application/x-www-form-urlencoded'
    }
  })
}

export function getBaseUrl () {
  return vueProps.axios.defaults.baseURL
}
