#!/usr/bin/python2
# -*- coding: utf-8 -*-

import multiprocessing as mp, os, signal, struct, sys, time
from StringIO import StringIO

from DisplayCAL import ICCProfile as ICCP, config, colormath, madvr, worker_base
from DisplayCAL.log import safe_print
from DisplayCAL.madvr import icc_device_link_to_madvr


def sigbreak_handler(sig, frame):
	sys._sigbreak = True

# SIGBREAK is Windows only. Use SIGINT as fallback
signal.signal(getattr(signal, "SIGBREAK", signal.SIGINT), sigbreak_handler)


def eecolor_to_madvr(eecolor_3dlut_filename, unity=False, colorspace=None,
					 hdr=None, logfile=sys.stdout,
					 convert_video_rgb_to_clut65=False, append_linear_cal=True):
	"""
	Convert eeColor 65^3 3D LUT to madVR 256^3 3D LUT using interpolation
	
	madvr 3D LUT will be written to:
	<eeColor 3D LUT filename without extension> + '.3dlut'
	
	"""

	filename, ext = os.path.splitext(eecolor_3dlut_filename)

	if not unity:
		# Read in eeColor 3D LUT data
		safe_print("Reading in eeColor 3D LUT", '"%s"' % eecolor_3dlut_filename)
		eecolor_3dlut_data = []
		with open(eecolor_3dlut_filename, "rb") as eecolor_3dlut:
			for line in eecolor_3dlut:
				line = line.strip()
				if not line or line.startswith("#"):
					continue
				values = [float(v) for v in line.split()]
				eecolor_3dlut_data.append(values)

		clutres = int(round(len(eecolor_3dlut_data) ** (1.0 / 3.0)))
		clutmax = clutres - 1.0

		# Fix input values (eeColor BRG) so sorting produces correct result
		n = 0
		for B in xrange(clutres):
			for R in xrange(clutres):
				for G in xrange(clutres):
					eecolor_3dlut_data[n][:3] = (v / clutmax for v in (R, G, B))
					n += 1

		# Sort eeColor 3D LUT data
		# (fastest increasing column from right to left: B -> G -> R)
		eecolor_3dlut_data.sort()

		# Create ICC device link profile from eeColor 3D LUT data
		safe_print("Creating device link from eeColor 3D LUT data...")
		link = ICCP.ICCProfile()
		link.connectionColorSpace = "RGB"
		link.profileClass = "link"
		link.tags.desc = ICCP.TextDescriptionType()
		link.tags.desc.ASCII = os.path.basename(filename)
		link.tags.cprt = ICCP.TextType("text\0\0\0\0No copyright", "cprt")
		link.tags.A2B0 = ICCP.LUT16Type()
		link.tags.A2B0.input = link.tags.A2B0.output = [[0, 65535]] * 3
		link.tags.A2B0.matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
		link.tags.A2B0.clut = []

		# Fill cLUT
		row = 0
		for a in xrange(clutres):
			for b in xrange(clutres):
				link.tags.A2B0.clut.append([])
				for c in xrange(clutres):
					values = [v * 65535 for v in eecolor_3dlut_data[row][3:]]
					link.tags.A2B0.clut[-1].append(values)
					row += 1

		# Write device link
		link.write(filename + ".icc")

	return icc_device_link_to_madvr(filename + ".icc", unity=unity,
									colorspace=colorspace, hdr=hdr,
									logfile=logfile,
									convert_video_rgb_to_clut65=convert_video_rgb_to_clut65,
									append_linear_cal=append_linear_cal)


if __name__ == "__main__":
	mp.freeze_support()
	result = None
	if sys.argv[1:] and not "--help" in sys.argv[1:]:
		config.initcfg()
		colorspace = None
		hdr = None
		for arg in sys.argv[1:]:
			if arg.lower().endswith(".txt"):
				fn = eecolor_to_madvr
			elif arg.lower().endswith(".icc") or arg.lower().endswith(".icm"):
				fn = icc_device_link_to_madvr
			else:
				if arg.startswith("--colorspace="):
					colorspace = [float(v) for v in arg[13:].split(",")]
				if arg.startswith("--hdr="):
					hdr = int(arg[6:])
				continue
			if not os.path.isabs(arg):
				arg = os.path.abspath(arg)
			if not os.path.isfile(arg) and not "--unity" in sys.argv[1:]:
				safe_print("Error: File not found:", arg)
				result = False
				break
			if result is not None:
				# Already processed some input file(s)
				safe_print("")
			try:
				result = fn(arg, unity="--unity" in sys.argv[1:],
							colorspace=colorspace, hdr=hdr,
							convert_video_rgb_to_clut65="--convert-video-rgb-to-clut65" in sys.argv[1:],
							append_linear_cal="--append-linear-cal" in sys.argv[1:])
			except Exception, exception:
				safe_print(exception)
				result = exception
		if result is None:
			safe_print("No filename given.")
	else:
		safe_print("Convert eeColor 65^3 to madVR 256^3 3D LUT (video levels in, video levels out)")
		safe_print("Author: Florian Hoech, licensed under the GPL version 3")
		safe_print("Usage: %s [--unity] [--batch] <name>.<target color space>.txt" % os.path.basename(sys.argv[0]))
		safe_print("Possible target color spaces: BT709, SMPTE_C, EBU_PAL, BT2020, DCI_P3")
		safe_print("Write output to <name>.<target color space>.3dlut")
		safe_print("")
		safe_print("  --unity                  Create unity (in = out) 3D LUT")
		safe_print("  --append-linear-cal      Append linear calibration")
		safe_print("  --batch                  Don't pause after processing")
		safe_print("")
		safe_print("Examples:")
		safe_print("  Convert SDR BT709 eeColor 3D LUT")
		safe_print("  %s eeColor.BT709.txt"  % os.path.basename(sys.argv[0]))
		safe_print("")
		safe_print("  Convert HDR BT2020 eeColor 3D LUT")
		safe_print("  %s eeColor.BT2020.HDR.txt"  % os.path.basename(sys.argv[0]))
		safe_print("")
		safe_print("  Convert HDR to SDR BT2020 eeColor 3D LUT")
		safe_print("  %s eeColor.BT2020.HDR2SDR.txt"  % os.path.basename(sys.argv[0]))
	if sys.stdout.isatty() and not "--batch" in sys.argv[1:]:
		raw_input("Press RETURN to exit")
	sys.exit(int(not result))
