const categories = require('../data/categories')
const parser = require('./parser')
const utils = require('./utils')
const file = require('./file')
const epg = require('./epg')

const db = {}

db.load = async function () {
  const files = await file.list()
  const codes = await epg.codes.load()
  for (const file of files) {
    const playlist = await parser.parsePlaylist(file)
    for (const channel of playlist.channels) {
      const code = codes.find(ch => ch['tvg_id'] === channel.tvg.id)
      if (code && Array.isArray(code.guides) && code.guides.length) {
        channel.tvg.url = code.guides[0]
      }

      db.channels.add(channel)

      for (const country of channel.countries) {
        if (!db.countries.has(country)) {
          db.countries.add(country)
        }
      }

      for (const language of channel.languages) {
        if (!db.languages.has(language)) {
          db.languages.add(language)
        }
      }
    }

    db.playlists.add(playlist)
  }
}

db.channels = {
  list: [],
  filter: null,
  duplicates: true,
  offline: true,
  nsfw: true,
  add(channel) {
    this.list.push(channel)
  },
  get() {
    let output
    if (this.filter) {
      switch (this.filter.field) {
        case 'countries':
          if (this.filter.value === 'undefined') {
            output = this.list.filter(channel => !channel.countries.length)
          } else {
            output = this.list.filter(channel =>
              channel.countries.map(c => c.code).includes(this.filter.value)
            )
          }
          break
        case 'languages':
          if (this.filter.value === 'undefined') {
            output = this.list.filter(channel => !channel.languages.length)
          } else {
            output = this.list.filter(channel =>
              channel.languages.map(c => c.code).includes(this.filter.value)
            )
          }
          break
        case 'category':
          if (this.filter.value === 'other') {
            output = this.list.filter(channel => !channel.category)
          } else {
            output = this.list.filter(
              channel => channel.category.toLowerCase() === this.filter.value
            )
          }
          break
      }
    } else {
      output = this.list
    }

    if (!this.duplicates) {
      const buffer = []
      output = output.filter(channel => {
        const info = channel.getInfo()
        if (buffer.includes(info)) return false
        buffer.push(info)

        return true
      })
    }

    if (!this.nsfw) {
      output = output.filter(channel => !channel.isNSFW())
    }

    if (!this.offline) {
      output = output.filter(channel => channel.status !== 'Offline')
    }

    this.nsfw = true
    this.duplicates = true
    this.offline = true
    this.filter = null

    return output
  },
  removeDuplicates() {
    this.duplicates = false

    return this
  },
  removeNSFW() {
    this.nsfw = false

    return this
  },
  removeOffline() {
    this.offline = false

    return this
  },
  all() {
    return this.list
  },
  forCountry(country) {
    this.filter = {
      field: 'countries',
      value: country.code
    }

    return this
  },
  forLanguage(language) {
    this.filter = {
      field: 'languages',
      value: language.code
    }

    return this
  },
  forCategory(category) {
    this.filter = {
      field: 'category',
      value: category.id
    }

    return this
  },
  count() {
    return this.get().length
  },
  sortBy(fields) {
    this.list = utils.sortBy(this.list, fields)

    return this
  }
}

db.countries = {
  list: [],
  has(country) {
    return this.list.map(c => c.code).includes(country.code)
  },
  add(country) {
    this.list.push(country)
  },
  all() {
    return this.list
  },
  count() {
    return this.list.length
  },
  sortBy(fields) {
    this.list = utils.sortBy(this.list, fields)

    return this
  }
}

db.languages = {
  list: [],
  has(language) {
    return this.list.map(c => c.code).includes(language.code)
  },
  add(language) {
    this.list.push(language)
  },
  all() {
    return this.list
  },
  count() {
    return this.list.length
  },
  sortBy(fields) {
    this.list = utils.sortBy(this.list, fields)

    return this
  }
}

db.categories = {
  list: categories,
  all() {
    return this.list
  },
  count() {
    return this.list.length
  }
}

db.playlists = {
  list: [],
  add(playlist) {
    this.list.push(playlist)
  },
  all() {
    return this.list
  },
  only(list = []) {
    return this.list.filter(playlist => list.includes(playlist.filename))
  },
  except(list = []) {
    return this.list.filter(playlist => !list.includes(playlist.filename))
  },
  sortBy(fields) {
    this.list = utils.sortBy(this.list, fields)

    return this
  },
  count() {
    return this.list.length
  }
}

module.exports = db