/*!
 * The MIT License (MIT)
 *
 * Copyright (c) 2019 Mark van Seventer
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

// Strict mode.
'use strict'

// Standard lib.
const path = require('path')

// Package modules.
const bubbleError = require('bubble-stream-error')
const sharp = require('sharp')
const urlTemplate = require('url-template')

// Local modules.
const queue = require('./queue')

// Configure.
const EXTENSIONS = {
  dz: '', // Determined by tile.container.
  jpeg: '.jpg',
  png: '.png',
  tiff: '.tiff',
  webp: '.webp'
}

// Exports.
module.exports = {
  // Convert a list of files.
  files: (input, output) => {
    const template = urlTemplate.parse(output) // Parse output template.

    // Process files.
    const promises = input.map((src) => {
      // Destination.
      src = path.resolve(src) // Absolute path.
      let dest = template.expand(path.parse(src))

      // Path separator for windows is encoded by url-template.
      // @see https://github.com/vseventer/sharp-cli/issues/8
      if (process.platform === 'win32') {
        dest = dest.split('%5C').join(path.sep)
      }

      // Absolute path.
      dest = path.resolve(dest)

      // Process file.
      const transformer = queue.drain(sharp(src))

      // If output was not a template, re-use source name.
      if (output === dest) {
        const defaultExt = path.extname(src)
        const desiredExt = transformer.options.formatOut
        dest = path.format({
          dir: output,
          name: path.basename(src, defaultExt),
          ext: desiredExt in EXTENSIONS ? EXTENSIONS[desiredExt] : defaultExt
        })
      }

      // Save to file.
      return transformer
        .toFile(dest)
        .then((info) => Object.assign(info, { src: src, path: dest }))
    })
    return Promise.all(promises)
  },

  // Convert a stream.
  stream: (inStream, outStream) => {
    return new Promise((resolve, reject) => {
      const transformer = queue.drain(sharp())

      // Pipe, and return as promise.
      bubbleError(inStream, transformer, outStream)
      inStream.pipe(transformer).pipe(outStream)
      outStream.once('error', reject)
      outStream.on('finish', resolve)
    })
  }
}