const models = [
	'android_station',
	'battery_bank',
	'black_hole',
	['matter_scanner', 'matter_scanner_working'],
	'pattern_storage',
	['matter_replicator', 'matter_replicator_working'],
	// 'matter_panel',
	['matter_decomposer', 'matter_decomposer_working'],
];

const fs = require('fs')
const _root = './src/main/resources/assets/overdrive_that_matters/'
const root_data = './src/main/resources/data/overdrive_that_matters/'
const root = _root + 'models/block/'

const time = Date.now()
process.stdout.write('Regenerating data files\n')

// "модель" горизонта событий / черной дыры
{
	const elements = []

	// сфера
	const layers = 32
	const radius = 2

	// создание
	for (let y = -layers / 2; y < layers / 2; y++) {
		for (let x = -layers / 2; x < layers / 2; x++) {
			for (let z = -layers / 2; z < layers / 2; z++) {
				const dist1 = Math.sqrt(x * x + y * y + z * z)

				if (dist1 <= radius) {
					elements.push({
						"from": [4 + (x + layers / 2) / layers * 8, 4 + (y + layers / 2) / layers * 8, 4 + (z + layers / 2) / layers * 8],
						"to": [4 + (x + layers / 2 + 1) / layers * 8, 4 + (y + layers / 2 + 1) / layers * 8, 4 + (z + layers / 2 + 1) / layers * 8],
						"faces": {
							"down":  { "texture": "#black_hole" },
							"up":    { "texture": "#black_hole" },
							"north": { "texture": "#black_hole" },
							"south": { "texture": "#black_hole" },
							"west":  { "texture": "#black_hole" },
							"east":  { "texture": "#black_hole" }
						}
					})
				}
			}
		}
	}

	fs.writeFileSync(root + 'black_hole.json', JSON.stringify({
		"parent": "block/block",
		"textures": {
			"black_hole": "overdrive_that_matters:block/black_hole"
		},
		"elements": elements
	}, null, '\t'))
}

const handle = fs.openSync('./src/main/java/ru/dbotthepony/mc/otm/shapes/BlockShapes.java', 'w')

fs.writeSync(handle, 'package ru.dbotthepony.mc.otm.shapes;\n\n\n')
fs.writeSync(handle, `// This file is regenerated on each gradle run. Do not edit it!\n`)
fs.writeSync(handle, 'public class BlockShapes {\n')

// модели блоков
for (const _model of models) {
	let model, path

	if (Array.isArray(_model)) {
		model = _model[0]
		path = _model[1]
	} else {
		model = _model
		path = _model
	}

	fs.writeSync(handle, '\tpublic static final BlockShape ' + model.toUpperCase() + ' = new BlockShape(\n')

	const obj = JSON.parse(fs.readFileSync(root + path + '.json', {encoding: 'utf-8'}))
	let first = true

	for (const elementID in obj.elements) {
		const element = obj.elements[elementID]

		if (element.rotation)
		    continue;

		const from = element.from
		const to = element.to

		if (first) {
			first = false
		} else {
			fs.writeSync(handle, ',\n')
		}

		fs.writeSync(handle, `\t\tnew SimpleCuboid(${from[0] / 16}d, ${from[1] / 16}d, ${from[2] / 16}d, ${to[0] / 16}d, ${to[1] / 16}d, ${to[2] / 16}d)`)
	}

	fs.writeSync(handle, '\n\t);\n\n')
}

fs.writeSync(handle, '}')
fs.closeSync(handle)

const facings = [
	{facing: "north", y: 0},
	{facing: "south", y: 180},
	{facing: "west", y: 270},
	{facing: "east", y: 90},
]

// генерируем 6 моделей паттернов
{
	const pattern_storage_pattern = JSON.parse(fs.readFileSync(root + 'pattern/pattern_storage_pattern.json'))

	const pattern_list = ['overdrive_that_matters:block/pattern/pattern_storage_pattern'];

	for (let i = 0; i < 7; i++) {
		pattern_storage_pattern.elements[0].from[0] -= 2
		pattern_storage_pattern.elements[0].to[0] -= 2

		fs.writeFileSync(root + 'pattern/pattern_storage_pattern' + i + '.json', JSON.stringify(pattern_storage_pattern, null, '\t'))
		pattern_list.push('overdrive_that_matters:block/pattern/pattern_storage_pattern' + i)
	}

	const base_model = 'overdrive_that_matters:block/pattern_storage'

	const blockstate = {
		multipart: []
	}

	for (const face of facings) {
		blockstate.multipart.push({
			when: {
				facing: face.facing
			},

			apply: {
				model: base_model,
				y: face.y ? face.y : undefined
			}
		});
	}

	for (let i = 0; i < 8; i++) {
		for (const face of facings) {
			blockstate.multipart.push({
				when: {
					facing: face.facing,
					["disk_" + i]: true
				},

				apply: {
					model: pattern_list[i],
					y: face.y ? face.y : undefined
				}
			})
		}
	}

	fs.writeFileSync(_root + 'blockstates/pattern_storage.json', JSON.stringify(blockstate, null, '\t'))
}

// Компоненты для крафта (как предмет)
{
	const components = [
		'tritanium_ingot',
		'matter_io_port',
		'matter_transform_matrix',
		'energy_bus',
		'electric_parts',
		// 'machine_frame',
		'tritanium_plate',
		'iron_plate',
		'copper_wiring',
		'gold_wiring',
		// 'portable_condensation_drive_casing',
		// 'portable_dense_condensation_drive_casing',
		'circuit_plating',
		'basic_control_circuit',
		'advanced_control_circuit',
	]

	for (const item of components) {
		fs.writeFileSync(_root + 'models/item/' + item + '.json', JSON.stringify(
			{
				"parent": "item/generated",
				"textures": {
					"layer0": "overdrive_that_matters:item/component/" + item
				}
			}
		, null, '\t'))
	}
}

// Drive Viewer
{
	const states = ['idle', 'working']
	const machine = 'drive_viewer'

	const blockstate = {
		multipart: []
	}

	for (const face of facings) {
		for (const state of states) {
			blockstate.multipart.push({
				when: {
					facing: face.facing,
					worker: state
				},

				apply: {
					model: 'overdrive_that_matters:block/' + machine + '_' + state,
					y: face.y ? face.y : undefined
				}
			});
		}

		blockstate.multipart.push({
			when: {
				facing: face.facing,
				drive: true
			},

			apply: {
				model: 'overdrive_that_matters:block/' + machine + '_drive_part',
				y: face.y ? face.y : undefined
			}
		});
	}

	fs.writeFileSync(_root + 'blockstates/' + machine + '.json', JSON.stringify(blockstate, null, '\t'))
}

// Машины с WorkerState
{
	const to_generate = ['matter_scanner', 'matter_replicator', 'matter_decomposer']
	const to_generate_semi = ['matter_bottler']
	const states = ['idle', 'working', 'error']
	const states_semi = ['idle', 'working']

	for (const machine of to_generate) {
		const blockstate = {
			multipart: []
		}

		for (const face of facings) {
			for (const state of states) {
				blockstate.multipart.push({
					when: {
						facing: face.facing,
						worker: state
					},

					apply: {
						model: 'overdrive_that_matters:block/' + machine + '_' + state,
						y: face.y ? face.y : undefined
					}
				});
			}
		}

		fs.writeFileSync(_root + 'blockstates/' + machine + '.json', JSON.stringify(blockstate, null, '\t'))
	}

	for (const machine of to_generate_semi) {
		const blockstate = {
			multipart: []
		}

		for (const face of facings) {
			for (const state of states_semi) {
				blockstate.multipart.push({
					when: {
						facing: face.facing,
						worker: state
					},

					apply: {
						model: 'overdrive_that_matters:block/' + machine + '_' + state,
						y: face.y ? face.y : undefined
					}
				});
			}
		}

		fs.writeFileSync(_root + 'blockstates/' + machine + '.json', JSON.stringify(blockstate, null, '\t'))
	}
}

// просто дропы блоков
{
	const blocks = [
		'cargo_crate',
		'matter_cable',
		'tritanium_block',
		'tritanium_striped_block',
		'carbon_fibre_block',

		'crate_red',
		'crate_blue',
		'crate_yellow',
		'crate_green',
		'crate_black',
		'crate_pink',
		'crate_purple',

		'tritanium_raw_block',
	]

	for (const name of blocks) {
		fs.writeFileSync(root_data + 'loot_tables/blocks/' + name + '.json', JSON.stringify({
			"type": "minecraft:block",
			"pools": [
				{
					"rolls": 1,
					"bonus_rolls": 0,
					"entries": [
						{
							"type": "minecraft:item",
							"name": "overdrive_that_matters:" + name
						}
					]
				}
			]
		}, null, '\t'))
	}
}

// Cargo Crate
{
	const blockstate = {
		variants: {}
	}

	for (const face of facings) {
		for (const open of [true, false]) {
			blockstate.variants['facing=' + face.facing + ',open=' + open] = {
				model: 'overdrive_that_matters:block/cargo_crate_' + (open ? 'open' : 'closed'),
				y: face.y
			}
		}
	}

	fs.writeFileSync(_root + 'blockstates/cargo_crate.json', JSON.stringify(blockstate, null, '\t'))
}

// Обычные блокстейты для ресурсов
{
	const blocks = [
		'tritanium_ore',
		'tritanium_raw_block',
		'deepslate_tritanium_ore',
	]

	for (const name of blocks) {
		const blockstate = {
			"variants": {
				"": [
					{
						"model": "overdrive_that_matters:block/" + name,
						"weight": 10
					},
				]
			}
		}

		for (const x of [0, 90, 180]) {
			for (const y of [0, 90, 180, 270]) {
				blockstate.variants[''].push({
					"model": "overdrive_that_matters:block/" + name,
					"weight": 1,
					"x": x,
					"y": y
				})
			}
		}

		fs.writeFileSync(_root + 'blockstates/' + name + '.json', JSON.stringify(blockstate, null, '\t'))

		fs.writeFileSync(_root + 'models/item/' + name + '.json', JSON.stringify({
			"parent": "overdrive_that_matters:block/" + name
		}, null, '\t'))

		fs.writeFileSync(_root + 'models/block/' + name + '.json', JSON.stringify({
			"parent": "block/cube_all",
			"textures": {
				"all": "overdrive_that_matters:block/resource/" + name
			}
		}, null, '\t'))
	}
}

// Обычные блокстейты
{
	const blocks = [
		'tritanium_block',
		'tritanium_striped_block',
		'carbon_fibre_block',

		'crate_red',
		'crate_blue',
		'crate_yellow',
		'crate_green',
		'crate_black',
		'crate_pink',
		'crate_purple',

		'black_hole',
	]

	const blocks2 = [
		'tritanium_block',
		'carbon_fibre_block',

		'crate_red',
		'crate_blue',
		'crate_yellow',
		'crate_green',
		'crate_black',
		'crate_pink',
		'crate_purple',
	]

	for (const name of blocks) {
		fs.writeFileSync(_root + 'blockstates/' + name + '.json', JSON.stringify({
			"variants": {
				"": {
					"model": "overdrive_that_matters:block/" + name
				}
			}
		}, null, '\t'))

		fs.writeFileSync(_root + 'models/item/' + name + '.json', JSON.stringify({
			"parent": "overdrive_that_matters:block/" + name
		}, null, '\t'))
	}

	for (const name of blocks2) {
		fs.writeFileSync(_root + 'models/block/' + name + '.json', JSON.stringify({
			"parent": "block/cube_all",
			"textures": {
				"all": "overdrive_that_matters:block/decorative/" + name
			}
		}, null, '\t'))
	}
}

// дропы с машин
{
	const drops = {
		android_station: ['energy_cap', 'battery_container'],
		battery_bank: ['battery_bank'],
		matter_capacitor_bank: ['matter_container'],

		drive_viewer: ['energy_cap', 'battery_container', 'drive_slot'],
		matter_bottler: ['energy_cap', 'battery_container', 'work_slots', 'work_flow', 'matter_capability'],

		matter_panel: ['tasks'],
		pattern_storage: ['patterns'],
	}

	const drops_workers = {
		matter_decomposer: ['work_slots', 'matter_capability'],
		matter_replicator: ['regular_slots', 'reserved_slots', 'matter_capability'],
		matter_scanner: ['work_slots'],
	}

	const combined = {}

	for (const name in drops) {
		combined[name] = drops[name]
	}

	for (const name in drops_workers) {
		drops_workers[name].push('work_ticks', 'current_job', 'energy_cap', 'battery_container')
		combined[name] = drops_workers[name]
	}

	for (const name in combined) {
		const values = combined[name]

		const state = {
			type: 'minecraft:block',
			pools: [
				{
					rolls: 1,
					bonus_rolls: 0,
					entries: [
						{
							type: 'minecraft:item',
							name: "overdrive_that_matters:" + name,
							functions: [
								{
									"function": "minecraft:copy_name",
									"source": "block_entity"
								},

								{
									"function": "minecraft:copy_nbt",
									"source": "block_entity",
									"ops": [
										{
											"source": "Name",
											"target": "BlockEntityTag.Name",
											"op": "replace"
										}
									]
								}
							]
						}
					]
				}
			]
		}

		for (const type of values) {
			state.pools[0].entries[0].functions[1].ops.push({
				"source": type,
				"target": "BlockEntityTag." + type,
				"op": "replace"
			})
		}

		fs.writeFileSync(root_data + 'loot_tables/blocks/' + name + '.json', JSON.stringify(state, null, '\t'))
	}
}

// генерация моделей для battery bank и matter capacitor bank
{
	let back = JSON.parse(fs.readFileSync(root + 'battery/battery_back.json'))
	let front = JSON.parse(fs.readFileSync(root + 'battery/battery_front.json'))
	const stepx = 12 / 3
	const stepy = 6

	const battery_list = ['overdrive_that_matters:block/battery/battery_front'];
	const matter_list = [];

	for (let i = 0; i < 5; i++) {
		if (i == 2) {
			front = JSON.parse(fs.readFileSync(root + 'battery/battery_front.json'))
			front.elements[0].from[1] += stepy
			front.elements[0].to[1] += stepy
		} else {
			front.elements[0].from[0] -= stepx
			front.elements[0].to[0] -= stepx
		}

		fs.writeFileSync(root + 'battery/battery_front' + i + '.json', JSON.stringify(front, null, '\t'))
		battery_list.push('overdrive_that_matters:block/battery/battery_front' + i)
	}

	battery_list.push('overdrive_that_matters:block/battery/battery_back')

	for (let i = 0; i < 5; i++) {
		if (i == 2) {
			back = JSON.parse(fs.readFileSync(root + 'battery/battery_back.json'))
			back.elements[0].from[1] += stepy
			back.elements[0].to[1] += stepy
		} else {
			back.elements[0].from[0] += stepx
			back.elements[0].to[0] += stepx
		}

		fs.writeFileSync(root + 'battery/battery_back' + i + '.json', JSON.stringify(back, null, '\t'))
		battery_list.push('overdrive_that_matters:block/battery/battery_back' + i)
	}

	for (let i = 0; i < battery_list.length; i++) {
		fs.writeFileSync(root + 'battery/matter_capacitor' + i + '.json', JSON.stringify({
			parent: battery_list[i],
			textures: {
				"1": "overdrive_that_matters:block/matterybank_core"
			}
		}, null, '\t'))

		matter_list.push('overdrive_that_matters:block/battery/matter_capacitor' + i)
	}

	const list = [
		['overdrive_that_matters:block/battery_bank', battery_list, 'blockstates/battery_bank.json'],
		['overdrive_that_matters:block/matter_capacitor_bank', matter_list, 'blockstates/matter_capacitor_bank.json'],
	]

	for (const [base_model, models, path] of list) {

		const blockstate = {
			multipart: []
		}

		for (const face of facings) {
			blockstate.multipart.push({
				when: {
					facing: face.facing
				},

				apply: {
					model: base_model,
					y: face.y ? face.y : undefined
				}
			});
		}

		for (let i = 0; i < 12; i++) {
			for (const face of facings) {
				blockstate.multipart.push({
					when: {
						facing: face.facing,
						["battery_" + i]: true
					},

					apply: {
						model: models[i],
						y: face.y ? face.y : undefined
					}
				})
			}
		}

		fs.writeFileSync(_root + path, JSON.stringify(blockstate, null, '\t'))
	}
}

process.stdout.write(`Regenerated data files in ${Date.now() - time}ms\n`)