import copy
from gk_output import *

from time import *
from sys import *
from struct import *

from key_records import *
from gk_global import *
from gk_shape import *
from gk_shape_modify import *

class gds_output_key(basic_gds_output):
	#----------------------------------------------------------------------------
	#Layout-level output functions
	#----------------------------------------------------------------------------

	def __list_library_header__(self, library):
		self.init_library_header(library)
		return ([KeyRecordTypeHeader,
				   " 5;\n",
				   KeyRecordTypeBgnLib,
				   ";\n",
				   KeyRecordTypeLastMod,
				   " ",
				   __str_date__(self.library.modified),
				   ";\n",
				   KeyRecordTypeLastAcc,
				   " ",
				   __str_date__(self.library.accessed),
				   ";\n",
				   KeyRecordTypeLibName,
				   " ",
				   self.library.name,
				   ";\n",
				   KeyRecordTypeUnits,
				   ";\n",
				   KeyRecordTypeUserUnits,
				   " ",
				   str(self.library.grid/self.library.unit),
				   ";\n",
				   KeyRecordTypePhysUnits,
				   " ",
				   str(self.library.grid),
				   ";\n"])

	def __list_library_footer__(self):
		self.fini_library_footer()
		return KeyRecordTypeEndLib + ";\n"

	def __list_structure_header__(self, item):
		sname = self.scramble_structure_name(item.name)
		return ([__str_comment__("Structure: " + item.name),
						__str_comment__(item.comment),
						KeyRecordTypeBgnStr,
						";\n",
						KeyRecordTypeCreation,
						" ",
						__str_date__(item.created),
						";\n",
						KeyRecordTypeLastMod,
						" ",
						__str_date__(item.modified),
						";\n",
						KeyRecordTypeStrName,
						" ",
						sname,
						";\n"
						])

	#generate the footer for any structure
	def __list_structure_footer__(self, item):
		sname = self.scramble_structure_name(item.name)
		return KeyRecordTypeEndStr + " " + sname + ";\n\n"

	#----------------------------------------------------------------------------
	#Element level output functions
	#----------------------------------------------------------------------------

	#text
	def list_label_element (self, item, additional_transform = None):
		T = item.transformation + additional_transform # make a copy because there is also the height
		coordinates = [T.__translate__(item.coordinate)]
		T.magnification *= item.height
		return [
			KeyRecordTypeText,
			"; ",
			self.__str_layer__(item.layer),
			"\n",
			KeyRecordTypeTextType,
			" 0;\n",
			KeyRecordTypePresentation,
			" ",
			str(item.h_alignment),
			",",
			str(item.v_alignment),
			",",
			str(item.font),
			";\n",
			KeyRecordTypePathType,
			" 1;\n",
			__str_transformation__(T),
			self.__str_coordinatelist__(coordinates),
			KeyRecordTypeString,
			" \"",
			item.text,
			"\";\n",
			KeyRecordTypeEndEl,
			";\n"
			]

	#references
	def list_sref_element (self, item, additional_transform = None):
		T = item.transformation + gds_translation(item.position) + additional_transform
		coordinates = T.apply([(0.0, 0.0)])
		sname = self.scramble_structure_name(item.reference.name)
		return (
			[KeyRecordTypeSRef,
			";\n",
			KeyRecordTypeSName,
			 " ",
			 sname,
			 ";\n",
			 __str_transformation__(T),
			 self.__str_coordinatelist__(coordinates),
			 KeyRecordTypeEndEl,
			 ";\n"
			 ])

	def list_aref_element (self, item, additional_transform = None):
		T = item.transformation + gds_translation(item.origin) + additional_transform
		sname = self.scramble_structure_name(item.reference.name)
		coordinates = T.apply([(0.0, 0.0), (item.n_o_periods[0] * item.period[0], 0.0),(0.0, item.n_o_periods[1] * item.period[1])])
		return ([
			KeyRecordTypeARef,
			";\n",
			KeyRecordTypeSName,
			" ",
			sname,
			";\n",
			KeyRecordTypeColRow,
			" { ",
			str(int(item.n_o_periods[0])),
			" , ",
			str(int(item.n_o_periods[1])),
			" };\n",
			__str_transformation__(T),
			self.__str_coordinatelist__(coordinates),
			KeyRecordTypeEndEl,
			";\n"
			])

	def list_box_element (self, item, additional_transform = None):
		T = item.transformation + additional_transform
		coordinates = T(shape_rect(item.center, item.box_size)).tolist()
		return ([
			KeyRecordTypeBox,
			"; ",
			self.__str_layer__(item.layer),
			KeyRecordTypeBoxType,
			" 0;\n",
			self.__str_coordinatelist__(coordinates),
			KeyRecordTypeEndEl,
			";\n"
			])

	def list_path_element (self, layer, coordinates, line_width, path_type):
		return ([
			KeyRecordTypePath,
			"; ",
			self.__str_layer__(layer),
			KeyRecordTypeDataType,
			" 0; ",
			KeyRecordTypePathType,
			" ",
			str(path_type),
			"; ",
			KeyRecordTypeWidth,
			" ",
			str(self.library.snap_value(self.__scale_value__(line_width))),
			";\n",
			self.__str_coordinatelist__(coordinates),
			KeyRecordTypeEndEl,
			";\n"
			])

	def list_boundary_element (self, layer, coordinates):
		return ([
			KeyRecordTypeBoundary,
			"; ",
			self.__str_layer__(layer),
			KeyRecordTypeDataType,
			" 0; \n",
			self.__str_coordinatelist__(coordinates),
			KeyRecordTypeEndEl,
			";\n"
			])

	#generate coordinate strings from a list of coordinates
	def __str_coordinatelist__ (self, coordinates):
		ret_data = ["   ",
				   KeyRecordTypeXY,
				   " ",
				   str(len(coordinates)),
				   ";\n"
				   ]
		#rounded_coordinates = self.round_coordinates(coordinates)
		for coord in coordinates:
			ret_data.extend([" ",
							 KeyRecordTypeX,
							 " ",
							 str(self.__scale_value__(coord[0])),
							 ";   ",
							KeyRecordTypeY,
							 " " ,
							str(self.__scale_value__(coord[1])),
							 ";\n"
							 ])
		return "".join(ret_data)


	def __str_layer__(self, layer):
		return "".join([ KeyRecordTypeLayer,
						" ",
						str(layer.number),
						"; "])

	#----------------------------------------------------------------------------
	# Low-level output
	#----------------------------------------------------------------------------

#Create the date strings
def __str_date__(T = time()):
	t = localtime(T)
	return "{" + strftime("%y-%m-%d  %H:%M:%S", t) + "}"

#Generate comment in the Key file
def __str_comment__(text):
	return "# " + text + "\n"


def __str_transformation__(transform):
	flip = transform.flip
	rotation = transform.rotation

	if flip:
		flipstr = "1"
	else:
		flipstr = "0"

	if transform.absolute_rotation:
		arotstr = "1"
	else:
		arotstr = "0"

	if transform.absolute_magnification:
		amagstr = "1"
	else:
		amagstr = "0"
		
	return "".join(["   ",
				KeyRecordTypeSTrans,
				" ",
				flipstr,
				",",
				amagstr ,
				",",
				arotstr,
				" ; ",
				KeyRecordTypeMag,
				" ",
				str(transform.magnification),
				" ; ",
				KeyRecordTypeAngle,
				" ",
				str(rotation),
				" ; \n"
				])
