/* globals XMLHttpRequest */

class FroideAPI {
  constructor (config) {
    this.config = config
  }
  getJson (url) {
    return new Promise((resolve, reject) => {
      var request = new XMLHttpRequest()
      request.open('GET', url, true)
      request.onload = function () {
        if (request.status >= 400) {
          try {
            return reject(JSON.parse(request.responseText))
          } catch (e) {
            return reject(request.responseText)
          }
        }
        resolve(JSON.parse(request.responseText))
      }
      request.onerror = function () {
        reject(request.statusText)
      }

      request.send()
    })
  }
  getObjects (promise) {
    return new Promise((resolve, reject) => {
      promise.then((data) => {
        return resolve(data.objects)
      })
        .catch((e) => reject(e))
    })
  }
  getJsonObjects (url) {
    return new Promise((resolve, reject) => {
      this.getJson(url)
        .then((data) => resolve(data.objects))
        .catch((e) => reject(e))
    })
  }
  getPublicBody (id) {
    let url = this.config.url.getPublicBody.replace(/\/0\//, `/${id}/`)
    return this.getJson(url)
  }

  autocompletePublicBody (term) {
    let query = encodeURIComponent(term)
    let url = this.config.url.autocompletePublicBody + '?query=' + query
    return this.getJsonObjects(url)
  }

  getUser () {
    return this.getJson(this.config.url.user)
  }

  getJsonForUrl (url, term, filters) {
    let hasParam = false
    if (term !== undefined && term) {
      hasParam = true
      url = url + '?q=' + encodeURIComponent(term)
    }
    if (filters !== undefined) {
      let f = []
      for (let key in filters) {
        let filterVal = filters[key]
        if (filterVal !== null) {
          if (!Array.isArray(filterVal)) {
            filterVal = [filterVal]
          }
          filterVal.forEach((val) => {
            f.push(key + '=' + encodeURIComponent(val))
          })
        }
      }
      url += hasParam ? '&' : '?'
      url += f.join('&')
    }
    return this.getJson(url)
  }

  searchPublicBodies (term, filters) {
    return this.getJsonForUrl(this.config.url.searchPublicBody, term, filters)
  }

  listPublicBodies (term, filters) {
    return this.getJsonForUrl(this.config.url.listPublicBodies, term, filters)
  }

  getLawsForPublicBodies (publicBodies, cachedLaws) {
    cachedLaws = cachedLaws || {}
    let lawIdMap = {}
    let lawIds = []
    publicBodies.forEach((pb) => {
      pb.laws.forEach((law) => {
        if (typeof law === 'string') {
          if (cachedLaws[law] !== undefined) {
            return
          }
          let parts = law.split('/')
          let lawId = parts[parts.length - 2]
          if (lawIdMap[lawId] === undefined) {
            lawIdMap[lawId] = true
            lawIds.push(lawId)
          }
        }
      })
    })
    if (lawIds.length === 0) {
      return Promise.resolve([])
    }
    return this.getJsonForUrl(this.config.url.listLaws, null, {
      'id': lawIds.join(',')
    }).then((data) => data.objects)
  }

  listJurisdictions (term, filters) {
    return this.getJsonForUrl(this.config.url.listJurisdictions, term, filters)
  }

  listCategories (term, filters) {
    return this.getJsonForUrl(this.config.url.listCategories, term, filters)
  }

  listClassifications (term, filters) {
    return this.getJsonForUrl(this.config.url.listClassifications, term, filters)
  }

  listGeoregions (term, filters) {
    return this.getJsonForUrl(this.config.url.listGeoregions, term, filters)
  }

  searchFoiRequests (term) {
    let query = encodeURIComponent(term)
    let url = this.config.url.searchRequests + '?q=' + query
    return this.getJsonObjects(url)
  }
}

function postData (url = '', data = {}, csrfToken, method = 'POST') {
  return window.fetch(url, {
    method: method,
    cache: 'no-cache',
    credentials: 'same-origin',
    headers: {

      'Content-Type': 'application/json',
      'X-Requested-With': 'XMLHttpRequest',
      'X-CSRFToken': csrfToken
    },
    body: JSON.stringify(data)
  }).then(response => response.json())
}

function putData (url = '', data = {}, csrfToken) {
  return postData(url, data, csrfToken, 'PUT')
}

function getData (url = '', headers = {}) {
  headers = headers || {}
  return window.fetch(url, {
    method: 'GET',
    cache: 'no-cache',
    credentials: 'same-origin',
    headers: {
      'Accept': 'application/json',
      'X-Requested-With': 'XMLHttpRequest',
      ...headers
    }
  }).then(response => response.json())
}

function getAllData (url = '', headers = {}, result = [], progress = null) {
  return new Promise((resolve, reject) => {
    getData(url, headers).then((data) => {
      if (Array.isArray(data.objects)) {
        result = [...result, ...data.objects]
      } else {
        result = [...result, ...data.objects.results]
      }
      if (data.meta.next) {
        if (progress) {
          progress(result)
        }
        getAllData(data.meta.next, headers, result).then(resolve).catch(reject)
      } else {
        resolve(result)
      }
    })
  })
}

function bustCache (url) {
  return window.fetch(url, {
    method: 'GET',
    cache: 'no-cache',
    credentials: 'same-origin',
    headers: {
      'pragma': 'no-cache',
      'cache-control': 'no-cache'
    }
  })
}

export {
  FroideAPI,
  postData,
  putData,
  getData,
  getAllData,
  bustCache
}

@@ -23,16 +23,64 @@
 est */%0A%0A
+const LANG_PATH = new RegExp(/%5E%5C/(%5Ba-z%5D%7B2%7D)%5C//)%0A
 class Fr
@@ -974,32 +974,38 @@
     this.getJson
+ForUrl
 (url)%0A        .t
@@ -1195,32 +1195,38 @@
 urn this.getJson
+ForUrl
 (url)%0A  %7D%0A%0A  aut
@@ -1652,24 +1652,217 @@
 term)%0A    %7D%0A
+    let langMatch%0A    if (document && document.location && (langMatch = LANG_PATH.exec(document.location.pathname))) %7B%0A      filters = filters %7C%7C %7B%7D%0A      filters.language = langMatch%5B1%5D%0A    %7D%0A
     if (filt

Add language parameter to JS API requests