import minecraftData from 'minecraft-data'
import minecraftAssets from 'minecraft-assets'
import fs from 'fs'

const latestData = minecraftData('1.20.2')

// dont touch, these are the ones that are already full box
const fullBoxInteractionShapes = [
  'dead_bush',
  'cave_vines_plant',
  'grass',
  'tall_seagrass',
  'spruce_sapling',
  'oak_sapling',
  'dark_oak_sapling',
  'birch_sapling',
  'seagrass',
  'nether_portal',
  'tall_grass',
  'lilac',
  'cobweb'
]

const ignoreStates = [
  'mangrove_propagule',
  'moving_piston'
]

// const

// to fix
const fullBoxInteractionShapesTemp = [
  'moving_piston',
  'lime_wall_banner',
  'gray_wall_banner',
  'weeping_vines_plant',
  'pumpkin_stem',
  'red_wall_banner',
  'crimson_wall_sign',
  'magenta_wall_banner',
  'melon_stem',
  'gray_banner',
  'spruce_sign',
  'pink_wall_banner',
  'purple_banner',
  'bamboo_sapling',
  'mangrove_sign',
  'cyan_banner',
  'blue_banner',
  'green_wall_banner',
  'yellow_banner',
  'black_wall_banner',
  'green_banner',
  'oak_sign',
  'jungle_sign',
  'yellow_wall_banner',
  'lime_banner',
  'tube_coral',
  'red_banner',
  'magenta_banner',
  'brown_wall_banner',
  'white_wall_banner',
]

const shapes = latestData.blockCollisionShapes;
const fullShape = shapes.shapes[1]
const outputJson = {}

let interestedBlocksNoStates = []
let interestedBlocksStates = []

const stateIgnoreStates = ['waterlogged']

const isNonInteractive = block => block.name.includes('air') || block.name.includes('water') || block.name.includes('lava') || block.name.includes('void')
const interestedBlocks = latestData.blocksArray.filter(block => {
  const shapeId = shapes.blocks[block.name]
  // console.log('shapeId', shapeId, block.name)
  if (!shapeId) return true
  const shape = typeof shapeId === 'number' ? shapes.shapes[shapeId] : shapeId
  if (shape.length === 0) return true
  // console.log(shape)
}).filter(b => !isNonInteractive(b)).filter(b => {
  if (fullBoxInteractionShapes.includes(b.name)) {
    outputJson[b.name] = fullShape
    return false
  }

  if (!b.states?.length || ignoreStates.includes(b.name) || b.states.every(s => stateIgnoreStates.every(state => s.name === state))) {
    interestedBlocksNoStates.push(b.name)
    return false
  } else {
    interestedBlocksStates.push(b.name)
    return false
  }
}).map(d => d.name)

const { blocksStates, blocksModels } = minecraftAssets(latestData.version.minecraftVersion)

const getShapeFromModel = (block,) => {
  const blockStates = JSON.parse(fs.readFileSync('./prismarine-viewer/public/blocksStates/1.19.1.json'))
  const blockState = blockStates[block];
  const perVariant = {}
  for (const [key, variant] of Object.entries(blockState.variants)) {
    // const shapes = (Array.isArray(variant) ? variant : [variant]).flatMap((v) => v.model?.elements).filter(Boolean).map(({ from, to }) => [...from, ...to]).reduce((acc, cur) => {
    //     return [
    //       Math.min(acc[0], cur[0]),
    //       Math.min(acc[1], cur[1]),
    //       Math.min(acc[2], cur[2]),
    //       Math.max(acc[3], cur[3]),
    //       Math.max(acc[4], cur[4]),
    //       Math.max(acc[5], cur[5])
    //     ]
    // })
    console.log(variant)
    const shapes = (Array.isArray(variant) ? variant : [variant]).flatMap((v) => v.model?.elements).filter(Boolean).map(({ from, to }) => [...from, ...to])
    perVariant[key] = shapes
    break
  }
  return perVariant
}

// console.log(getShapeFromModel('oak_button'))

// const addShapeIf = {
//   redstone: [
//     ['east', 'up', shape]
//   ]
// }

const needBlocksStated = {}

const groupedBlocksRules = {
  // button: block => block.includes('button'),
  // pressure_plate: block => block.includes('pressure_plate'),
  // sign: block => block.includes('_sign'),
  // sapling: block => block.includes('_sapling'),
}
const groupedBlocksOutput = {}

outer: for (const interestedBlock of [...interestedBlocksNoStates, ...interestedBlocksStates]) {
  for (const [block, func] of Object.entries(groupedBlocksRules)) {
    if (func(interestedBlock)) {
      groupedBlocksOutput[block] ??= []
      groupedBlocksOutput[block].push(interestedBlock)
      continue outer
    }
  }

  const hasStates = interestedBlocksStates.includes(interestedBlock);
  if (hasStates) {
    const states = blocksStates[interestedBlock]
    if (!states) {
      console.log('no states', interestedBlock)
      continue
    }
    if (!states.variants) {
      if (!states.multipart) {
        console.log('no variants', interestedBlock)
        continue
      }
      let outputStates = {}
      for (const {when} of states.multipart) {
        if (when) {
          for (const [key, value] of Object.entries(when)) {
            if (key === 'OR') {
              for (const or of value) {
                for (const [key, value] of Object.entries(or)) {
                  const str = `${key}=${value}`
                  outputStates[str] = true
                }
              }
              continue
            }
            const str = `${key}=${value}`
            outputStates[str] = true
          }
        }
      }
      needBlocksStated[interestedBlock] = outputStates
      continue
    }
    if (Object.keys(states.variants).length === 1 && states.variants['']) {
      needBlocksStated[interestedBlock] = false
    } else {
      needBlocksStated[interestedBlock] = Object.fromEntries(Object.entries(states.variants).map(([key, value]) => [key, true]))
    }
  } else {
    needBlocksStated[interestedBlock] = false
  }
  // let vars = []
  // Object.keys(variants).forEach(variant => {
  //   if (variant !== '') vars.push(variant)
  // })
  // needBlocksVariants.push({
  //   block: interestedBlock,
  //   variants: vars
  // })
}

fs.writeFileSync('scripts/needBlocks.json', JSON.stringify(needBlocksStated))

// console.log(interestedBlocks.includes('lever'))

// read latest block states

// read block model elements & combine
