const tone = require('node-tone')
const MediaProbeData = require('../scanner/MediaProbeData')
const Logger = require('../Logger')

/*
Sample dump from tone
{
  "audio": {
    "bitrate": 17,
    "format": "MPEG-4 Part 14",
    "formatShort": "MPEG-4",
    "sampleRate": 44100.0,
    "duration": 209284.0,
    "channels": {
      "count": 2,
      "description": "Stereo (2/0.0)"
    },
    "frames": {
      "offset": 42168,
      "length": 446932
    "metaFormat": [
      "mp4"
    ]
  },
  "meta": {
    "album": "node-tone",
    "albumArtist": "advplyr",
    "artist": "advplyr",
    "composer": "Composer 5",
    "comment": "testing out tone metadata",
    "encodingTool": "audiobookshelf",
    "genre": "abs",
    "itunesCompilation": "no",
    "itunesMediaType": "audiobook",
    "itunesPlayGap": "noGap",
    "narrator": "Narrator 5",
    "recordingDate": "2022-09-10T00:00:00",
    "title": "Test 5",
    "trackNumber": 5,
    "chapters": [
      {
        "start": 0,
        "length": 500,
        "title": "chapter 1"
      },
      {
        "start": 500,
        "length": 500,
        "title": "chapter 2"
      },
      {
        "start": 1000,
        "length": 208284,
        "title": "chapter 3"
      }
    ],
    "embeddedPictures": [
      {
        "code": 14,
        "mimetype": "image/png",
        "data": "..."
    },
    "additionalFields": {
      "test": "Test 5"
    }
  },
  "file": {
    "size": 530793,
    "created": "2022-09-10T13:32:51.1942586-05:00",
    "modified": "2022-09-10T14:09:19.366071-05:00",
    "accessed": "2022-09-11T13:00:56.5097533-05:00",
    "path": "C:\\Users\\Coop\\Documents\\NodeProjects\\node-tone\\samples",
    "name": "m4b.m4b"
  }

*/

function bitrateKilobitToBit(bitrate) {
  if (isNaN(bitrate) || !bitrate) return 0
  return Number(bitrate) * 1000
}

function msToSeconds(ms) {
  if (isNaN(ms) || !ms) return 0
  return Number(ms) / 1000
}

function parseProbeDump(dumpPayload) {
  const audioMetadata = dumpPayload.audio
  const audioChannels = audioMetadata.channels || {}
  const audio_stream = {
    bit_rate: bitrateKilobitToBit(audioMetadata.bitrate), // tone uses Kbps but ffprobe uses bps so convert to bits
    codec: null,
    time_base: null,
    language: null,
    channel_layout: audioChannels.description || null,
    channels: audioChannels.count || null,
    sample_rate: audioMetadata.sampleRate || null
  }

  let chapterIndex = 0
  const chapters = (dumpPayload.meta.chapters || []).map(chap => {
    return {
      id: chapterIndex++,
      start: msToSeconds(chap.start),
      end: msToSeconds(chap.start + chap.length),
      title: chap.title || ''
    }
  })

  var video_stream = null
  if (dumpPayload.meta.embeddedPictures && dumpPayload.meta.embeddedPictures.length) {
    const mimetype = dumpPayload.meta.embeddedPictures[0].mimetype
    video_stream = {
      codec: mimetype === 'image/png' ? 'png' : 'jpeg'
    }
  }

  const tags = { ...dumpPayload.meta }
  delete tags.chapters
  delete tags.embeddedPictures

  const fileMetadata = dumpPayload.file
  var sizeBytes = !isNaN(fileMetadata.size) ? Number(fileMetadata.size) : null
  var sizeMb = sizeBytes !== null ? Number((sizeBytes / (1024 * 1024)).toFixed(2)) : null
  return {
    format: audioMetadata.format || 'Unknown',
    duration: msToSeconds(audioMetadata.duration),
    size: sizeBytes,
    sizeMb,
    bit_rate: audio_stream.bit_rate,
    audio_stream,
    video_stream,
    chapters,
    tags
  }
}

module.exports.probe = (filepath, verbose = false) => {
  if (process.env.TONE_PATH) {
    tone.TONE_PATH = process.env.TONE_PATH
  }

  return tone.dump(filepath).then((dumpPayload) => {
    if (verbose) {
      Logger.debug(`[toneProber] dump for file "${filepath}"`, dumpPayload)
    }
    const rawProbeData = parseProbeDump(dumpPayload)
    const probeData = new MediaProbeData()
    probeData.setDataFromTone(rawProbeData)
    return probeData
  }).catch((error) => {
    Logger.error(`[toneProber] Failed to probe file at path "${filepath}"`, error)
    return {
      error
    }
  })
}

module.exports.rawProbe = (filepath) => {
  if (process.env.TONE_PATH) {
    tone.TONE_PATH = process.env.TONE_PATH
  }

  return tone.dump(filepath).then((dumpPayload) => {
    return dumpPayload
  }).catch((error) => {
    Logger.error(`[toneProber] Failed to probe file at path "${filepath}"`, error)
    return {
      error
    }
  })
}