const nbt = require('prismarine-nbt')
// TOOD: remove this
nbt.float = value => ({ type: 'float', value })

const { networkBiomesToMcDataSchema, mcDataSchemaToNetworkBiomes } = require('./transforms')

module.exports = (data, staticData) => {
  let hasDynamicDimensionData = false

  return {
    loadDimensionCodec (codec) {
      const dimensionCodec = nbt.simplify(codec)

      const chat = dimensionCodec['minecraft:chat_type']?.value
      if (chat) {
        data.chatFormattingById = {}
        data.chatFormattingByName = {}
        for (const chatType of chat) {
          const d = chatType.element?.chat?.decoration ?? chatType.element?.chat
          if (!d) continue
          const n = {
            id: chatType.id,
            name: chatType.name,
            formatString: staticData.language[d.translation_key] || d.translation_key /* chat type minecraft:raw has the formatString given directly by the translation key */,
            parameters: d.parameters
          }
          data.chatFormattingById[chatType.id] = n
          data.chatFormattingByName[chatType.name] = n
        }
      }

      const dimensions = dimensionCodec['minecraft:dimension_type']?.value
      if (dimensions) {
        data.dimensionsById = {}
        data.dimensionsByName = {}
        for (const { name, id, element } of dimensions) {
          const n = name.replace('minecraft:', '')
          const d = {
            name: n,
            minY: element.min_y,
            height: element.height
          }
          data.dimensionsById[id] = d
          data.dimensionsByName[n] = d
        }
      }

      const biomes = dimensionCodec['minecraft:worldgen/biome']?.value
      if (!biomes) {
        return // no biome data
      }

      data.biomes = []
      data.biomesByName = {}
      data.biomesArray = []

      biomes.map(e => networkBiomesToMcDataSchema(e, staticData))

      const allBiomes = []
      for (const { name, id, element } of biomes) {
        data.biomes[id] = element
        data.biomesByName[name] = element
        allBiomes.push(element)
      }
      data.biomesArray = allBiomes
      hasDynamicDimensionData = true
    },

    writeDimensionCodec () {
      const codec = {}

      if (data.version['<']('1.16')) {
        return codec // no dimension codec in 1.15
      } else if (data.version['<']('1.16.2')) {
        return staticData.loginPacket.dimensionCodec
      } else if (data.version['>=']('1.16.2')) {
        // Keep the old dimension codec data if it exists (re-encoding)
        // We don't have this data statically, should probably be added to mcData
        if (data.dimensionsArray) {
          codec['minecraft:dimension_type'] = nbt.comp({
            type: nbt.string('minecraft:dimension_type'),
            value: nbt.list(nbt.comp(
              data.dimensionsArray.map(dimension => ({
                name: dimension.name,
                id: dimension.id,
                element: dimension.element
              }))
            ))
          })
        } else {
          codec['minecraft:dimension_type'] = staticData.loginPacket.dimensionCodec.value['minecraft:dimension_type']
        }

        // if we have dynamic biome data (re-encoding), we can count on biome.effects
        // being in place. Otherwise, we need to use static data exclusively, e.g. flying squid.
        codec['minecraft:worldgen/biome'] = nbt.comp({
          type: nbt.string('minecraft:worldgen/biome'),
          value: nbt.list(nbt.comp(mcDataSchemaToNetworkBiomes(hasDynamicDimensionData ? data.biomesArray : null, staticData)))
        })
        // 1.19
        codec['minecraft:chat_type'] = staticData.loginPacket.dimensionCodec?.value?.['minecraft:chat_type']
      }

      return nbt.comp(codec)
    }
  }
}
