const ID3Writer = require('browser-id3-writer')
const Metaflac = require('metaflac-js2')
const fs = require('fs')

function tagID3(path, track, save){
  const songBuffer = fs.readFileSync(path)
  const tag = new ID3Writer(songBuffer)

  if (save.title) tag.setFrame('TIT2', track.title)

  if (save.artist && track.artists.length){
    if (save.multiArtistSeparator == "default"){
      tag.setFrame('TPE1', track.artists)
    }else{
      if (save.multiArtistSeparator == "nothing"){
        tag.setFrame('TPE1', track.mainArtist.name)
      } else {
        tag.setFrame('TPE1', track.artistString)
      }
      // Tag ARTISTS is added to keep the multiartist support when using a non standard tagging method
      // https://picard-docs.musicbrainz.org/en/appendices/tag_mapping.html#artists
      tag.setFrame('TXXX', {
        description: 'ARTISTS',
        value: track.artists
      })
    }
  }

  if (save.album) tag.setFrame('TALB', track.album.title)

  if (save.albumArtist && track.album.artists.length){
    if (save.singleAlbumArtist && track.album.mainArtist.save){
      tag.setFrame('TPE2', track.album.mainArtist.name)
    } else {
      tag.setFrame('TPE2', track.album.artists)
    }
  }

  if (save.trackNumber){
    let trackNumber = String(track.trackNumber)
    if (save.trackTotal) trackNumber += `/${track.album.discTotal}`
    tag.setFrame('TRCK', trackNumber)
  }
  if (save.discNumber){
    let discNumber = String(track.discNumber)
    if (save.discTotal) discNumber += `/${track.album.discTotal}`
    tag.setFrame('TPOS', discNumber)
  }

  if (save.genre) tag.setFrame('TCON', track.album.genre)
  if (save.year) tag.setFrame('TYER', track.date.year)

  // Referencing ID3 standard
  // https://id3.org/id3v2.3.0#TDAT
  // The 'Date' frame is a numeric string in the DDMM format.
  if (save.date) tag.setFrame('TDAT', "" + track.date.day + track.date.month)

  if (save.length) tag.setFrame('TLEN', parseInt(track.duration)*1000)
  if (save.bpm) tag.setFrame('TBPM', track.bpm)
  if (save.label) tag.setFrame('TPUB', track.album.label)
  if (save.isrc) tag.setFrame('TSRC', track.ISRC)
  if (save.barcode) tag.setFrame('TXXX', {
    description: 'BARCODE',
    value: track.album.barcode
  })
  if (save.explicit) tag.setFrame('TXXX', {
    description: 'ITUNESADVISORY',
    value: track.explicit ? "1" : "0"
  })
  if (save.replayGain) tag.setFrame('TXXX', {
    description: 'REPLAYGAIN_TRACK_GAIN',
    value: track.replayGain
  })
  if (save.lyrics && track.lyrics.unsync) tag.setFrame('USLT', track.lyrics.unsync)

  // TODO: Uncomment when implemented in lib
  /*
  if (save.syncedLyrics && track.lyrics.syncID3) tag.setFrame('SYLT', {
    text: track.lyrics.syncID3,
    type: 1,
    timestampFormat: 2,
    useUnicodeEncoding: true
  })
  */

  let involvedPeople = []
  Object.keys(track.contributors).forEach(role => {
    if (['author', 'engineer', 'mixer', 'producer', 'writer'].includes(role)){
      track.contributors[role].forEach(person => {
        involvedPeople.push([role, person])
      })
    } else if (role === 'composer' && save.composer){
      tag.setFrame('TCOM', track.contributors.composer)
    }
  })
  // TODO: Uncomment when implemented in lib
  // if (involvedPeople.length && save.involvedPeople) tag.setFrame('IPLS', involvedPeople)

  if (save.copyright) tag.setFrame('TCOP', track.copyright)
  if (save.savePlaylistAsCompilation && track.playlist || track.album.recordType == "compile")
    tag._setIntegerFrame('TCMP', 1) // tag.setFrame('TCMP', 1)

  if (save.source){
    tag.setFrame('TXXX', {
      description: 'SOURCE',
      value: 'Deezer'
    })
    tag.setFrame('TXXX', {
      description: 'SOURCEID',
      value: track.id
    })
  }

  if (save.cover && track.album.embeddedCoverPath){
    const coverArrayBuffer = fs.readFileSync(track.album.embeddedCoverPath)
    tag.setFrame('APIC', {
      type: 3,
      data: coverArrayBuffer,
      description: 'cover',
      useUnicodeEncoding: save.coverDescriptionUTF8
    })
  }
  tag.addTag()

  fs.writeFileSync(path, Buffer.from(tag.arrayBuffer))
}

function tagFLAC(path, track, save){
  const flac = new Metaflac(path)
  flac.removeAllTags()

  if (save.title) flac.setTag(`TITLE=${track.title}`)

  if (save.artist && track.artists.length){
    if (save.multiArtistSeparator == "default"){
      track.artists.forEach(artist => {
        flac.setTag(`ARTIST=${artist}`)
      })
    }else{
      if (save.multiArtistSeparator == "nothing"){
        flac.setTag(`ARTIST=${track.mainArtist.name}`)
      } else {
        flac.setTag(`ARTIST=${track.artistString}`)
      }
      // Tag ARTISTS is added to keep the multiartist support when using a non standard tagging method
      // https://picard-docs.musicbrainz.org/en/appendices/tag_mapping.html#artists
      track.artists.forEach(artist => {
        flac.setTag(`ARTISTS=${artist}`)
      })
    }
  }

  if (save.album) flac.setTag(`ALBUM=${track.album.title}`)

  if (save.albumArtist && track.album.artists.length){
    if (save.singleAlbumArtist && track.album.mainArtist.save){
      flac.setTag(`ALBUMARTIST=${track.album.mainArtist.name}`)
    } else {
      track.album.artists.forEach(artist => {
        flac.setTag(`ALBUMARTIST=${artist}`)
      })
    }
  }

  if (save.trackNumber) flac.setTag(`TRACKNUMBER=${track.trackNumber}`)
  if (save.trackTotal) flac.setTag(`TRACKTOTAL=${track.album.trackTotal}`)
  if (save.discNumber) flac.setTag(`DISCNUMBER=${track.discNumber}`)
  if (save.discTotal) flac.setTag(`DISCTOTAL=${track.album.discTotal}`)
  if (save.genre){
    track.album.genre.forEach(genre => {
      flac.setTag(`GENRE=${genre}`)
    })
  }

  // YEAR tag is not suggested as a standard tag
  // Being YEAR already contained in DATE will only use DATE instead
  // Reference: https://www.xiph.org/vorbis/doc/v-comment.html#fieldnames
  if (save.date) flac.setTag(`DATE=${track.dateString}`)
  else if (save.year) flac.setTag(`DATE=${track.date.year}`)

  if (save.length) flac.setTag(`LENGTH=${parseInt(track.duration)*1000}`)
  if (save.bpm) flac.setTag(`BPM=${track.bpm}`)
  if (save.label) flac.setTag(`PUBLISHER=${track.album.label}`)
  if (save.isrc) flac.setTag(`ISRC=${track.ISRC}`)
  if (save.barcode) flac.setTag(`BARCODE=${track.album.barcode}`)
  if (save.explicit) flac.setTag(`ITUNESADVISORY=${track.explicit ? "1" : "0"}`)
  if (save.replayGain) flac.setTag(`REPLAYGAIN_TRACK_GAIN=${track.replayGain}`)
  if (save.lyrics && track.lyrics.unsync) flac.setTag(`LYRICS=${track.lyrics.unsync}`)

  Object.keys(track.contributors).forEach(role => {
    if (['author', 'engineer', 'mixer', 'producer', 'writer', 'composer'].includes(role)){
      if (save.involvedPeople && role != 'composer' || save.composer && role == 'composer')
        track.contributors[role].forEach(person => {
          flac.setTag(`${role.toUpperCase()}=${person}`)
        })
    } else if (role === 'musicpublisher' && save.involvedPeople){
      track.contributors.musicpublisher.forEach(person => {
        flac.setTag(`ORGANIZATION=${person}`)
      })
    }
  })

  if (save.copyright) flac.setTag(`COPYRIGHT=${track.copyright}`)
  if (save.savePlaylistAsCompilation && track.playlist || track.album.recordType == "compile")
    flac.setTag('COMPILATION=1')

  if (save.source){
    flac.setTag('SOURCE=Deezer')
    flac.setTag(`SOURCEID=${track.id}`)
  }

  if (save.cover && track.album.embeddedCoverPath){
    flac.importPicture(track.album.embeddedCoverPath)
  }

  flac.save()
}

module.exports = {
  tagID3,
  tagFLAC
}