import { HttpError } from 'flaska'
import decode from '../jwt/decode.mjs'
import config from '../config.mjs'

export function verifyToken(ctx) {
  let token = ctx.query.get('token')
  if (!token) {
    throw new HttpError(422, 'Token is missing in query')
  }

  let org = config.get('sites')
  let sites = {}
  for (let key in org) {
    if (org.hasOwnProperty(key)) {
      sites[key] = org[key].keys
    }
  }

  try {
    let decoded = decode(token, sites, [])
    return decoded.iss
  } catch (err) {
    ctx.log.error(err, 'Error decoding token: ' + token)
    throw new HttpError(422, 'Token was invalid')
  }
}

export function throwIfNotPublic(site) {
  let sites = config.get('sites')
  if (!sites[site] || sites[site].public !== true) {
    throw new HttpError(404, `Requested site ${site} did not exist`)
  }
}

const validObjectOperations = [
  'resize',
  'extend',
  'flatten',
]

const validNumberOperations = [
  'blur',
  'trim',
]

export function verifyBody(ctx) {
  let keys = Object.keys(ctx.req.body)

  for (let key of keys) {
    if (key === 'filename' || key === 'path') {
      throw new HttpError(422, 'Body item with name filename or path is not allowed')
    }
    let item = ctx.req.body[key]

    if (typeof(item) !== 'object'
        || !item
        || Array.isArray(item)) {
      throw new HttpError(422, `Body item ${key} was not valid`)
    }

    if (typeof(item.format) !== 'string'
        || !item.format
        || validObjectOperations.includes(item.format)
        || item.format === 'out') {
      throw new HttpError(422, `Body item ${key} missing valid format`)
    }

    if (typeof(item[item.format]) !== 'object'
        || !item[item.format]
        || Array.isArray(item[item.format])) {
      throw new HttpError(422, `Body item ${key} options for format ${item.format} was not valid`)
    }

    if (item.out != null) {
      if (typeof(item.out) !== 'string'
          || (item.out !== '' && item.out !== 'file' && item.out !== 'base64')
      ) {
        throw new HttpError(422, `Body item ${key} key out was invalid`)
      }
    }

    for (let operation of validObjectOperations) {
      if (item[operation] != null) {
        if (typeof(item[operation]) !== 'object'
            || Array.isArray(item[operation])) {
          throw new HttpError(422, `Body item ${key} key ${operation} was invalid`)
        }
      }
    }

    for (let operation of validNumberOperations) {
      if (item[operation] != null) {
        if (typeof(item[operation]) !== 'number') {
          throw new HttpError(422, `Body item ${key} key ${operation} was invalid`)
        }
      }
    }
  }
}
