import sys
import ruamel.yaml as yaml
from ruamel.yaml import YAML
from ruamel.yaml.scalarstring import PreservedScalarString, preserve_literal
from ruamel.yaml.nodes import Node
from collections import OrderedDict
import math
import time

def generatorToString(generator, seperator = " ", func = str):
	return seperator.join(func(v) for v in generator)

def imageToArray2d(image, size):
	dataStr = generatorToString(image, seperator = "\n", func = lambda v: generatorToString(v, seperator = " "))
	result = Array2d("{0[0]} {0[1]} [\n{1:s}\n]".format(size, dataStr))
	#result.value = "{0[0]} {0[1]}, [{1:s}]".format(size, dataStr)
	return result

def resizeList(aList, scale):
	counter = 0.0
	for element in aList:
		counter += scale
		for _ in range(math.floor(counter)):
			yield element
		counter -= math.floor(counter)

def resizeImage(image, sizeMultiplier):
	return (resizeList(line, sizeMultiplier) for line in resizeList(image, sizeMultiplier))

def convertScan(scan, sizeMultiplier):
	image = scan["image"]
	scan.popitem("image")
	newSize = (math.floor(len(image[0]) * sizeMultiplier), \
			   math.floor(len(image) * sizeMultiplier) )
	
	scan["image"] = imageToArray2d(resizeImage(image, sizeMultiplier), newSize)

def convertFile(inFilePath, outFilePath, sizeMultiplier = 1, loader = YAML(typ="safe").load, dumper = YAML(typ="safe").dump):
	startTime = time.time()

	# open file:
	with open(inFilePath) as inFile:
		fileData = loader(inFile)

	# check version of document:
	fileData["format"]["identifier"] = "MLZ.StressSpec.2.0 / proposal 0.3"

	for scan in fileData["measurement"]["scan"]:
		convertScan(scan, sizeMultiplier)
		
	with open(outFilePath, "w") as outFfile:
		dumper(fileData, outFfile)
		#json.dump(fileData, outFfile)

	endTime = time.time()
	return endTime - startTime

##########################################################################

# represents an Array2d object that can be converted to and from yaml.
# its yaml tag is !array2d.
class Array2d:
    yaml_tag = "!array2d"

    def __init__(self, data):
        self.data = data

    @classmethod
    def to_yaml(cls, representer, node):
        return representer.represent_scalar(cls.yaml_tag,
                                            node.data, style="|")

    @classmethod
    def from_yaml(cls, constructor, node):
        return cls(*node.value)


# "rt" is round-trip (slow)
# "safe" is faster :), but discards comments and ignores yaml output style :(
yamlLoader=YAML(typ="rt")
yamlDumper=YAML(typ="rt")

yamlLoader.register_class(Array2d)
yamlDumper.register_class(Array2d)

# define style for output yaml:
yamlDumper.default_flow_style = False
yamlDumper.indent(sequence = 4, mapping = 4, offset = 0)


for i in range(1, len(sys.argv)):
	if 1==i%2:
		inFilePath = sys.argv[i]
		outFilePath =  sys.argv[i+1]
		print(inFilePath + " -> " + outFilePath)
		dt = convertFile(inFilePath, outFilePath, 
			sizeMultiplier = 1,
			loader = yamlLoader.load, 
			dumper = yamlDumper.dump
		)
		print("{0:>7,} ms".format(int(dt * 1000)))