'use strict'

const querystring = require('querystring')
const common = require('./common')

const log = require('../logger').create('middleware:source-files')

function findByPath (files, path) {
  return Array.from(files).find((file) => file.path === path)
}

function composeUrl (url, basePath, urlRoot) {
  return url
    .replace(urlRoot, '/')
    .replace(/\?.*$/, '')
    .replace(/^\/absolute/, '')
    .replace(/^\/base/, basePath)
}

// Source Files middleware is responsible for serving all the source files under the test.
function createSourceFilesMiddleware (filesPromise, serveFile, basePath, urlRoot) {
  return function (request, response, next) {
    const requestedFilePath = composeUrl(request.url, basePath, urlRoot)
    // When a path contains HTML-encoded characters (e.g %2F used by Jenkins for branches with /)
    const requestedFilePathUnescaped = composeUrl(querystring.unescape(request.url), basePath, urlRoot)

    request.pause()

    log.debug(`Requesting ${request.url}`)
    log.debug(`Fetching ${requestedFilePath}`)

    return filesPromise.then(function (files) {
      // TODO(vojta): change served to be a map rather then an array
      const file = findByPath(files.served, requestedFilePath) || findByPath(files.served, requestedFilePathUnescaped)
      const rangeHeader = request.headers['range']

      if (file) {
        const acceptEncodingHeader = request.headers['accept-encoding']
        const matchedEncoding = Object.keys(file.encodings).find(
          (encoding) => new RegExp(`(^|.*, ?)${encoding}(,|$)`).test(acceptEncodingHeader)
        )
        const content = file.encodings[matchedEncoding] || file.content

        serveFile(file.contentPath || file.path, rangeHeader, response, function () {
          if (/\?\w+/.test(request.url)) {
            common.setHeavyCacheHeaders(response) // files with timestamps - cache one year, rely on timestamps
          } else {
            common.setNoCacheHeaders(response) // without timestamps - no cache (debug)
          }
          if (matchedEncoding) {
            response.setHeader('Content-Encoding', matchedEncoding)
          }
        }, content, file.doNotCache)
      } else {
        next()
      }

      request.resume()
    })
  }
}

createSourceFilesMiddleware.$inject = [
  'filesPromise', 'serveFile', 'config.basePath', 'config.urlRoot'
]

exports.create = createSourceFilesMiddleware
