package ru.dbotthepony.kstarbound.tools

import com.google.gson.GsonBuilder
import ru.dbotthepony.kommons.io.readString
import ru.dbotthepony.kommons.io.readVarInt
import ru.dbotthepony.kstarbound.io.readHeader
import ru.dbotthepony.kstarbound.json.readJsonElement
import java.io.BufferedInputStream
import java.io.DataInputStream
import java.io.File
import java.io.OutputStreamWriter
import java.util.Scanner
import kotlin.system.exitProcess

fun main(vararg args: String) {
	var originalFile = args.getOrNull(0)
	val scanner = System.`in`?.let(::Scanner)
	var interactive = false

	if (originalFile == null) {
		if (scanner == null) {
			System.err.println("Usage: <original file path> [output file path]")
			System.err.println("By default, new file is put in the same folder as original file")
			System.err.println("with '.json' extension added to it")
			exitProcess(1)
		} else {
			println("Input filename:")
			originalFile = scanner.nextLine()
			interactive = true
		}
	}

	val f = File(originalFile!!).absoluteFile

	if (!f.exists()) {
		System.err.println("File $f does not exist")
		exitProcess(1)
	}

	if (!f.isFile) {
		System.err.println("$f is not a file")
		exitProcess(1)
	}

	var newFile = args.getOrNull(1)

	if (newFile == null) {
		if (interactive) {
			val def = f.parent + "/" + f.name + ".json"
			println("Output filename [$def]:")
			val read = scanner!!.nextLine()

			if (read == "") {
				newFile = def
			} else {
				newFile = read!!
			}
		} else {
			newFile = f.parent + "/" + f.name + ".json"
		}
	}

	val new = File(newFile)

	if (!new.parentFile.exists()) {
		System.err.println("Output directory ${new.parent} does not exist")
		exitProcess(1)
	}

	if (!new.parentFile.isDirectory) {
		System.err.println("Output directory ${new.parent} is not a directory")
		exitProcess(1)
	}

	if (new.exists() && !new.isFile) {
		System.err.println("Output path $new already exists and it is not a file")
		exitProcess(1)
	}

	if (interactive && new.exists()) {
		println("$new already exists. Overwrite? [Y/n]")
		var next = scanner!!.nextLine()
		if (next == "") next = "y"

		if (next.lowercase()[0] != 'y') {
			System.err.println("Halt")
			exitProcess(1)
		}
	}

	try {
		val t = System.nanoTime()
		val dataStream = DataInputStream(BufferedInputStream(f.inputStream()))

		dataStream.readHeader("SBVJ01")
		val name = dataStream.readString(dataStream.readVarInt())
		val magic = dataStream.read()
		val version = dataStream.readInt()
		val data = dataStream.readJsonElement()
		val gson = GsonBuilder().setPrettyPrinting().create()

		dataStream.close()

		println("$f:")
		println("JSON Name: $name")
		println("Version: $version")
		println("Magic: $magic")
		println("JSON Type: ${data::class.simpleName}")

		new.delete()
		val output = OutputStreamWriter(new.outputStream())
		gson.toJson(data, output)
		output.close()

		println("Successfully written data to $new ${"in %.2f ms".format(((System.nanoTime() - t) / 1_000L) / 1_000.0)}")
		exitProcess(0)
	} catch(err: Throwable) {
		System.err.println(err)
		exitProcess(1)
	}
}
