const radio = require('radio-stream')
const request = require('request')
const irc = require('irc-upd')
const models = require('./models').models
const Help = require('./libs/Help')
const ArtistSong = require('./libs/ArtistSong')
const When = require('./libs/When')
const Statistics = require('./libs/Statistics')
const List = require('./libs/List')
const Preferences = require('./libs/Preferences')

// Init des librairies
const artistSong = new ArtistSong(models)
const when = new When(models)
const stats = new Statistics(models)
const list = new List(models)
const preferences = new Preferences(models)

let titlePath = null
let artistPath = null
if (process.env.STREAM_PATH_TITLE) {
  titlePath = process.env.STREAM_PATH_TITLE.split('.')
}
if (process.env.STREAM_PATH_ARTIST) {
  artistPath = process.env.STREAM_PATH_ARTIST.split('.')
}

// Stockage du morceau en cours de lecture
let currentSong = {
  artist: null,
  title: null
}
let previousSong = {
  artist: null,
  title: null
}

// Initialisation du bot IRC
const bot = new irc.Client(process.env.IRC_SERVER, process.env.IRC_NICKNAME, {
  userName: process.env.IRC_USER_NAME,
  realName: process.env.IRC_REAL_NAME,
  password: process.env.IRC_PASSWORD,
  channels: [process.env.IRC_CHANNEL]
})

const checkCurrentSong = () => {
  previousSong = currentSong
  // Just for debug
  console.info(`Now playing: ${currentSong.artist} - ${currentSong.title}`)

  // Publish song on IRC channel
  bot.say(process.env.IRC_CHANNEL, `${process.env.RADIO_ALIAS} : ${currentSong.artist} - ${currentSong.title}`)

  // Save song for history
  artistSong.saveCurrent({
    radio: process.env.RADIO_ALIAS,
    artist: currentSong.artist,
    title: currentSong.title
  })

  // Notify some people ?
  artistSong.notify(botSay, process.env.IRC_CHANNEL, currentSong)
}

// Initialisation du stream radio
if (!process.env.STREAM_TYPE || process.env.STREAM_TYPE === 'radio') {
  const stream = radio.createReadStream(process.env.STREAM_URL)

  stream.on('connect', function () {
    console.info('Radio Stream connected!')
    console.info(stream.headers)
  })

  // Listener on new song
  stream.on('metadata', function (data) {
    console.log('RAW DATA:', data)
    // let song = data.replace(/[^A-Za-z 0-9 .,?""!@#$%^&*()-_=+;:<>/\\|}{[\]`~]*/g, '')
    const song = data.substring(13, data.length - 1).replace(/\0/g, '').replace('\';', '')

    // Extract artist = title from song
    const splitted = song.split(' - ')
    const artist = splitted[0]
    const title = splitted[1]

    currentSong = {
      title: title,
      artist: artist
    }

    checkCurrentSong()
  })
} else {
  setInterval(() => {
    request({
      method: 'GET',
      url: process.env.STREAM_URL
    },
    (error, response, body) => {
      if (!error && response.statusCode === 200) {
        const res = JSON.parse(process.env.STREAM_PARSE ? body.replace('updateFromMediaItem(', '').replace(');', '') : body)

        let title = null
        let artist = null

        switch (process.env.STREAM_TYPE) {
          case 'json':
            title = res[titlePath[0]]
            for (let i = 1; i < titlePath.length; i += 1) {
              title = title[titlePath[i]]
            }
            artist = res[artistPath[0]]
            for (let i = 1; i < artistPath.length; i += 1) {
              artist = artist[artistPath[i]]
            }

            currentSong = {
              title: title,
              artist: artist
            }
            break
          case 'alien':
            try {
              for (let i = 0; i < res.length; i += 1) {
                if (res[i].name === 'Cult') {
                  currentSong = {
                    title: res[i].nowPlaying.track.title,
                    artist: res[i].nowPlaying.track.artist
                  }
                  break
                }
              }
            } catch (e) {
              console.error('ERR:', e)
            }
            break
        }

        if (previousSong.title !== currentSong.title && previousSong.artist !== currentSong.artist) {
          checkCurrentSong()
        }
      } else {
        console.error('ERR:', error)
      }
    })
  }, 4000)
}

// Gestion des erreurs du bot IRC
bot.addListener('error', function (message) {
  console.error('ERR:', message)
})

/**
 * Fonction permettant de publier un message sur IRC
 * @param  {String} where
 * @param  {String} what
 */
const botSay = (where, what) => {
  bot.say(where, what)
}

/**
 * Gestion des actions
 * @param  {String} where
 * @param  {String} message
 * @param  {String} from
 */
const actions = (where, message, from) => {
  const exploded = message.split(' ')

  // Le message publiƩ est pour le bot
  if (exploded[0].indexOf(process.env.IRC_NICKNAME) === 0) {
    switch (exploded[1]) {
      case '!artist':
      case '!song':
        artistSong.action(exploded[1].replace('!', ''), botSay, from, currentSong, exploded)
        break
      case '!help':
        Help.show(botSay, where, exploded)
        break
      case '!when':
        when.action(botSay, where, exploded)
        break
      case '!stats':
        stats.action(botSay, where, exploded)
        break
      case '!list':
        list.action(botSay, where, exploded)
        break
      case '!notifications':
        preferences.notifications(botSay, where, from, exploded)
        break
      case '!stream':
        botSay(where, `${process.env.RADIO_ALIAS} : ${process.env.PUBLIC_RADIO_STREAM}`)
        break
      default:
        botSay(where, 'Commande inconnue, tape !help si tu es perdu')
        break
    }
  }
}

// Listener for public message
bot.addListener(`message${process.env.IRC_CHANNEL}`, function (from, to, message) {
  actions(process.env.IRC_CHANNEL, message.args.splice(1).join(' '), from)
})
// Listener for private message
bot.addListener('pm', function (from, to, message) {
  actions(from, message.args.join(' '), from)
})
// Say hello!
if (process.env.SAY_HELLO && process.env.SAY_HELLO === 'true') {
  bot.addListener('join', (channel, who) => {
  // Welcome them in!
    if (who !== process.env.IRC_NICKNAME) {
      botSay(process.env.IRC_CHANNEL, 'Hello ' + who + '! Have a metal day! \\m/(-.-)\\m/')
    }
  })
}