const fs = require('fs')
const yaml = require('js-yaml')
const path = require('path')
const { createHash } = require('crypto')

module.exports = {
  readYaml,
  saveYaml,
  saveJson,
  addYamlComment,
  suffixFilename,
  changeExtension,
  getYamlComment,
  sha
}

function readYaml (filename) {
  return yaml.safeLoad(fs.readFileSync(filename, 'utf-8'))
}

/**
 * Save file as yml.
 *
 * @param {string} filename - File name.
 * @param {object} object - Raw JSON data.
 * @param {string} comment - Comment block to add to the top of the file.
 */
function saveYaml (filename, object, comment = '') {
  fs.mkdirSync(path.dirname(filename), { recursive: true })
  fs.writeFileSync(filename, `${formatYamlComment(comment)}${yaml.safeDump(object, { noRefs: true, lineWidth: 120 })}`)
}

function getYamlComment (filename) {
  return fs
    .readFileSync(filename, 'utf-8')
    .split(/^[^#]/im)[0]
    .trim()
}

function saveJson (filename, object) {
  fs.mkdirSync(path.dirname(filename), { recursive: true })
  fs.writeFileSync(filename, JSON.stringify(object, null, 2))
}

function addYamlComment (filename, comment = '') {
  const content = fs.readFileSync(filename, 'utf-8')
  const formatted = formatYamlComment(comment)
  if (content.indexOf(formatted) > -1) return // do not write duplicated comment
  fs.writeFileSync(filename, `${formatted}${content}`)
}

function formatYamlComment (comment = '') {
  if (!comment) return ''
  return `${comment
    .split('\n')
    .map(l => (l.startsWith('#') ? l : `# ${l}`))
    .join('\n')}\n`
}

/**
 * Adds suffix to the filename respecting extension.
 *
 * @param {string} filename - File name.
 * @param {string} suffix - Suffix to add to filename.
 * @returns {string} Suffixed filename.
 * @example
 * suffixFilename('/path/to/foo.json', '-mysuffix')
 * // returns '/path/to/foo-mysuffix.json'
 */
function suffixFilename (filename, suffix) {
  return path.join(
    path.dirname(filename),
    `${path.basename(filename, path.extname(filename))}${suffix}${path.extname(filename)}`
  )
}

/**
 * Change extension of a filename.
 *
 * @param {string} filename - Original filename.
 * @param {string} extension - New extension starting with dot, e.g. ".yml".
 * @returns {string} - New value.
 */
function changeExtension (filename, extension) {
  return path.join(path.dirname(filename), path.basename(filename, path.extname(filename)) + extension)
}

function sha (data) {
  return createHash('sha256')
    .update(data)
    .digest('hex')
}
