# -*- coding: utf-8 -*-

# Copyright 2011-2014, extragroup GmbH, Pottkamp 19, 48149 Münster, Germany
# All rights reserved
#
# All information contained herein is, and remains the property of
# extragroup GmbH and its suppliers, if any. The intellectual and
# technical concepts contained herein are proprietary to extragroup GmbH
# and its suppliers and are protected by trade secret or copyright law.
# Dissemination of this information or reproduction of this material is
# strictly forbidden unless prior written permission is obtained from
# extragroup GmbH

from interiorcad.cuttinglistexport.csvbase import CuttinglistExportCSVBase
import logging
#import interiorcad.backend.exportsettingsfile
import interiorcad.interface.configurationkeys as ConfigurationKeys
from interiorcad.interface.geometry.edges import EdgeData
from interiorcad.backend.dosfilenamecreator import DosFilenameCreator
import re

class SwissSoft(CuttinglistExportCSVBase):

	def __init__(self, **keywords):
		super().__init__(**keywords)

		self.EXTENSION = 'txt'
		self.EXPORT_LOCATION = self.getCuttinglistConfiguration().get('export-location', 'file')  # | clipboard
		self.SCOPE_OF_EXPORT = self.getCuttinglistConfiguration().get('scope-of-export',
																	  'partsonly')  # | partsandfittings | fittingsonly
		self.CUMULATE_COVERINGS = self.getCuttinglistConfiguration().getAsBool('cumulate-coverings', False)
		self.CUMULATE_FITTINGS = self.getCuttinglistConfiguration().getAsBool('cumulate-fittings', True)
		self.CUMULATE_WORKPIECES = self.getCuttinglistConfiguration().get('cumulate-workpieces', 'none')
		self.NC_PROGRAM_DISPLAY_NAME_DEFINITION = self.getCuttinglistConfiguration().get('nc-program-display-name-definition', 'namewithextension')
		self.sortierung = self.CONFIGURED_SORTING_CRITERIA = self.cuttinglistConfiguration.get('sorting-criteria',self.getDefaultSortingCriteria(**keywords) if hasattr(self,'getDefaultSortingCriteria') else self.DEFAULT_SORTING_CRITERIA)



		#self.exportsettingsfile = interiorcad.backend.exportsettingsfile.ExportSettingsFile()
		self.csvdelimiter = '\t'
		#self.EXTENSION = 'txt'
		#self.OUTPUT_ENCODING = 'latin1' #self.OUTPUT_ENCODING = 'windows-1252' #latin1, 'iso-8859-1'
		#self.EXPORT_LOCATION = self.getCuttinglistConfiguration().get('export-location', 'file')  # | clipboard
		#self.SCOPE_OF_EXPORT = self.getCuttinglistConfiguration().get('scope-of-export', 'partsonly')  # | partsandfittings | fittingsonly
		#self.CUMULATE_FITTINGS = self.getCuttinglistConfiguration().getAsBool('cumulate-fittings', True)
		self.EXPORT_FORMAT = 'SwissSoft'
		self.SpalteB = self.getCuttinglistConfiguration().get('SpalteB', 'PosNr')
		self.SpalteD = self.getCuttinglistConfiguration().get('SpalteD', 'BName')
		self.SpalteE = self.getCuttinglistConfiguration().get('SpalteE', 'Moebel')
		self.SpalteV = self.getCuttinglistConfiguration().get('SpalteV', 'leer')
		self.SpalteVKey = self.getCuttinglistConfiguration().get('SpalteVKey', '')
		self.Drehung = self.getCuttinglistConfiguration().get('Drehung', '90CW')
		self.DrehungGrain = self.getCuttinglistConfiguration().get('DrehungGrain', '0')
		self.SHORT_PART_NAMES = self.getCuttinglistConfiguration().getAsBool('short-part-names', False)


		if self.SpalteB == 'PosNr':
			self.CONFIGURED_SORTING_CRITERIA = self.POSITION_SORTING_CRITERIA

		#self.KantenIDKeineKante = self.getCuttinglistConfiguration().get('KantenID keine Kante', '')
		#self.MoePosNrn = [] #Liste mit Positionsnummern
		#self.MoePosBezn = [] #Liste mit Positionsnamen
		#self.Moebelnamen = [] #Liste mit Moebelnamen
		#self.PosIDs = [] #Liste mit PosNr+Moebelname
		self.counter = 0
		#self.export_process = '_'
		self.KanteVN = 'N'
		self.KaDict = {'Unknown': ['0','-'], '': ['0','-'], 'Continuous': ['2',self.KanteVN], 'Discontinuous': ['1',self.KanteVN], 'Miter': ['3',self.KanteVN]}
		self.RoationDict = {'0': 0, '90CW': -90, '90CCW': 90, '180CCW':180}


	def getJointAsString(self, jointId):
		if jointId == EdgeData.JOINT_MITER:
			return 'Miter'
		elif jointId == EdgeData.JOINT_CONTINUOUS:
			return 'Continuous'
		elif jointId == EdgeData.JOINT_DISCONTINUOUS:
			return 'Discontinuous'
		elif not jointId or jointId == EdgeData.JOINT_NOEDGE:
			return ''
		else:
			return 'Unknown'

	def doCuttinglistExport(self, **keywords):
		if self.EXPORT_LOCATION == 'clipboard':
			self.doClipboardExport(**keywords)
		elif self.EXPORT_LOCATION == 'fileandclipboard':
			self.doFileExport(**keywords)
			self.doClipboardExport(**keywords)
		else:
			self.doFileExport(**keywords)

	def openExportPath(self, **keywords):
		if 'file' in self.EXPORT_LOCATION:
			super().openExportPath(**keywords)


	def getHeaderLine(self, **keywords):
		return ('Auftrag', 'Position', 'Pos.Bezeichnung',
				'Baugruppe', 'Bezeichnung', 'Trägermaterial', 'Anzahl',
				'Laenge', 'Breite', 'Dicke',
				'Kante_V', 'Dicke_V', 'Kante_H', 'Dicke_H', 'Kante_L', 'Dicke_L', 'Kante_R', 'Dicke_R',
				'Belag_I', 'Belag_A', 'Bemerkung', 'Zumass', 'Kantencode', 'KantenVN', 'NC_Haupt', 'NC_Neben',
				'NC_Format', 'Maserrichtung', 'Zumass l/b', 'KaV_Zu', 'KaH_Zu', 'KaL_Zu', 'KaR_Zu', 'Besch1', 'Besch2'
				)

	def GruppeGenerieren(self, Moebelname, MoePosNr, MoePosBeschreibung, Bauteilname):
		Gruppe = MoePosNr + MoePosBeschreibung
		if Gruppe == None or Gruppe == '':
			Gruppe = Moebelname
		if Gruppe == None or Gruppe == '':
			Gruppe = Bauteilname
		self.counter += 1
		return Gruppe

	def getGrain(self, grain):  # For Length/Width as defined in interiorcad, dimensions and edges stay the same.

		if grain == self.GRAIN_LENGTHWISE:
			return 'laengs'
		elif grain == self.GRAIN_CROSSWISE:  # Actually impossible, because using edgesGrainDirection.
			return 'quer'
		else:  # grain == self.GRAIN_NONE
			return 'keine'



	def TranslateStragety(self, s):
		StratDict={'nc-compatible':'Gemäss NC-Ausgabe','sawn-size':'Rohmass','sawn-size-with-addition':'Rohmass + Zugabe','finished-size':'Fertigmass','finished-size-with-addition':'Fertigmass+Zugabe'}
		return StratDict.get(s)



	def KantenCode(self, Ka1, Ka2, Ka3, Ka4, Ka1S, Ka2S, Ka3S, Ka4S, Ka1E, Ka2E, Ka3E, Ka4E, Reihenfolge = [4,3,1,2]):
		# 1 bündig, 2 vorstehend, 3 Gehrung

		reihenfolge_dict = {'vorne' : Reihenfolge[0], 'hinten' : Reihenfolge[1], 'links' : Reihenfolge[2], 'rechts' : Reihenfolge[3]}

		KanteVN_SS = []
		Kantencode_SS = []


		if Ka1 != '':
			if Ka3 == '':
				Kantencode_SS.append('1')
			else:
				Kantencode_SS.append(self.KaDict[Ka1E][0])

			KanteVN_SS.append(self.KanteVN)

		else:
			Kantencode_SS.append('0')
			KanteVN_SS.append('-')


		if Ka2 != '':
			if Ka4 == '':
				Kantencode_SS.append('1')
			else:
				Kantencode_SS.append(self.KaDict[Ka2E][0])

			KanteVN_SS.append(self.KanteVN)

		else:
			Kantencode_SS.append('0')
			KanteVN_SS.append('-')

		if Ka3 != '':
			if Ka2 == '':
				Kantencode_SS.append('1')
			else:
				Kantencode_SS.append(self.KaDict[Ka3E][0])

			KanteVN_SS.append(self.KanteVN)

		else:
			Kantencode_SS.append('0')
			KanteVN_SS.append('-')


		if Ka4 != '':
			if Ka1 == '':
				Kantencode_SS.append('1')
			else:
				Kantencode_SS.append(self.KaDict[Ka4E][0])

			KanteVN_SS.append(self.KanteVN)

		else:
			Kantencode_SS.append('0')
			KanteVN_SS.append('-')

		vorne_index = Reihenfolge[0]-1
		hinten_index = Reihenfolge[1]-1
		links_index = Reihenfolge[2]-1
		rechts_index = Reihenfolge[3]-1

		return KanteVN_SS[vorne_index]+KanteVN_SS[hinten_index]+KanteVN_SS[links_index]+KanteVN_SS[rechts_index], \
			   Kantencode_SS[vorne_index] + Kantencode_SS[hinten_index] + Kantencode_SS[links_index] + Kantencode_SS[rechts_index]




	def getElements(self, **keywords):
		self.export_process = '_'
		entry = keywords['entry']
		projectInfo = keywords['projectInfo']
		positionInfo = keywords['positionInfo']
		istBeschlag = 'istBeschlag' in keywords
		#Moebelname = self.asString(data=positionInfo['CabinetName'], **keywords)
		PosBeschreibung = self.asString(data=positionInfo["PositionDescription"], **keywords)
		#Bauteilname = self.asString(key='unit_unitid', **keywords)

		###############Zumass

		Zumass = ''  # 0 kein Zumass / 1 Zumass / leer wie in WL vor dem Import eingestellt
		ZumassNative = '0'

		if self.SpalteV == 'Auto':
			notFormat = re.split('\s+', self.SpalteVKey)
			notFormat.append('dummy')
			Zumass = '1' #Spalte Obsolet
			ZumassNative = self.configuration.sizingAddition * 2 #neue Spalte

			for s in notFormat:
				if s in self.asString(key='part_description', **keywords).lower():
					Zumass = '0'
					ZumassNative = '0'

					break


		else:
			if self.SpalteV == 'leer':
				Zumass = ZumassNative = Ka1Zu = Ka2Zu = Ka3Zu = Ka4Zu = ''
			else:
				Zumass = self.asString(key='part_comment', **keywords)

				if Zumass == '0':
					ZumassNative = '0'
				elif Zumass == '1':
					ZumassNative = self.asString(key='part_comment', **keywords)


		############Zumass auf Kanten aufgeteilt

		if ZumassNative == '0':
			Ka1Zu = Ka2Zu = Ka3Zu = Ka4Zu = 0

		else:
			Ka1Zu = Ka2Zu = Ka3Zu = Ka4Zu = self.configuration.sizingAddition

		if entry.isFitting():
			Ka1Zu = Ka2Zu = Ka3Zu = Ka4Zu = ''
			Zumass = ''

		PosNr = self.asString(data=positionInfo["PositionNumber"], **keywords)
		Pos = PosNr

		BauteilName = self.asString(key='unit_unitid', **keywords)
		BauteilName = DosFilenameCreator().createDosFilename(BauteilName) if self.SHORT_PART_NAMES else BauteilName
		BauteilBez = self.asString(key='part_description', **keywords)
		BauteilBez = DosFilenameCreator().createDosFilename(BauteilBez) if self.SHORT_PART_NAMES else BauteilBez

		Bauteil = BauteilBez
		Moebelname = self.asString(data=positionInfo['CabinetName'], **keywords)



		if self.SpalteB == 'empty':
			Pos = ''
		else:
			if PosNr == '': #Keine Position
				Pos = '999'

			try:
				if not isinstance(eval(Pos), int): # Position Nr ist keine Zahl
					Pos = '998'
			except:
				Pos = '998'



		if self.SpalteD == 'BName':
			Bauteil = BauteilName

		Gruppe = Moebelname

		if Moebelname == '': #Kein Möbelname
			if self.asString(data=positionInfo["PositionNumber"], **keywords) == '': #Keine Position
				Gruppe = 'Position frei'

			else: #Positionsbezeichnung gibt Gruppename falls Position vorhanden ist
				if PosBeschreibung == '':
					Gruppe = PosNr

				else:
					Gruppe = PosBeschreibung

		else:
			if self.SpalteE == 'MoPos':
				if Moebelname != '':
					if PosNr != '':
						Gruppe = PosNr + ' ' + Moebelname
					else:
						Gruppe = Moebelname
				else:
					if PosNr != '':
						Gruppe = PosNr
					else:
						Gruppe = '999'



		#Swiss Soft Spaltenreihenfolge Kanten 4312

		KanteVN = ''
		Kantencode = ''  # Aufpassen! Kantenreihenfolge ist 4 3 1 2 beim Export

		Ka1 = self.asString(data=entry.edgesGrainDirection.front.supplierID, **keywords)
		Ka2 = self.asString(data=entry.edgesGrainDirection.back.supplierID, **keywords)
		Ka3 = self.asString(data=entry.edgesGrainDirection.left.supplierID, **keywords)
		Ka4 = self.asString(data=entry.edgesGrainDirection.right.supplierID, **keywords)

		Ka1D = self.asCoordinate(data=entry.edgesGrainDirection.front.thickness, **keywords)
		Ka2D = self.asCoordinate(data=entry.edgesGrainDirection.back.thickness, **keywords)
		Ka3D = self.asCoordinate(data=entry.edgesGrainDirection.left.thickness, **keywords)
		Ka4D = self.asCoordinate(data=entry.edgesGrainDirection.right.thickness, **keywords)

		Ka1S = 'Continuous'
		Ka2S = 'Continuous'
		Ka3S = 'Discontinuous'
		Ka4S = 'Discontinuous'

		#Bezieht sich auf den Export V H L R

		Breite = self.asCoordinate(data=entry.boardWidthGrainDirection, **keywords)
		Laenge = self.asCoordinate(data=entry.boardLengthGrainDirection, **keywords)

		Ka1E = self.getJointAsString(self.getDataAsString(data=entry.edgesGrainDirection.front.jointEnd, **keywords))
		Ka2E = self.getJointAsString(self.getDataAsString(data=entry.edgesGrainDirection.back.jointEnd, **keywords))
		Ka3E = self.getJointAsString(self.getDataAsString(data=entry.edgesGrainDirection.left.jointEnd, **keywords))
		Ka4E = self.getJointAsString(self.getDataAsString(data=entry.edgesGrainDirection.right.jointEnd, **keywords))

		Ka1S = self.getJointAsString(self.getDataAsString(data=entry.edgesGrainDirection.front.jointStart, **keywords))
		Ka2S = self.getJointAsString(self.getDataAsString(data=entry.edgesGrainDirection.back.jointStart, **keywords))
		Ka3S = self.getJointAsString(self.getDataAsString(data=entry.edgesGrainDirection.left.jointStart, **keywords))
		Ka4S = self.getJointAsString(self.getDataAsString(data=entry.edgesGrainDirection.right.jointStart, **keywords))

		Drehung = self.RoationDict[self.Drehung] + self.RoationDict[self.DrehungGrain]



		#self.RoationDict = {'0': 0, '90CW': -90, '90CCW': 90}
		rotation_real = Drehung
		if entry.grain == 1: #quer
			rotation_real = Drehung - 90

		if Drehung == -90: #Bisher
			KantenVN, Kantencode = self.KantenCode(Ka1, Ka2, Ka3, Ka4, Ka1S, Ka2S, Ka3S, Ka4S, Ka1E, Ka2E, Ka3E, Ka4E, [4, 3, 1, 2])
			ExportBreite = Breite
			ExportLaenge = Laenge

			Kante_V 	= Ka4; Kante_V_D 	= Ka4D
			Kante_H 	= Ka3; Kante_H_D 	= Ka3D
			Kante_L 	= Ka1; Kante_L_D 	= Ka1D
			Kante_R 	= Ka2; Kante_R_D 	= Ka2D


		if Drehung == 0:
			KantenVN, Kantencode = self.KantenCode(Ka1, Ka2, Ka3, Ka4, Ka1S, Ka2S, Ka3S, Ka4S, Ka1E, Ka2E, Ka3E, Ka4E, [1, 2, 3, 4])
			ExportBreite = Laenge
			ExportLaenge = Breite

			Kante_V = Ka1; Kante_V_D = Ka1D
			Kante_H = Ka2; Kante_H_D = Ka2D
			Kante_L = Ka3; Kante_L_D = Ka3D
			Kante_R = Ka4; Kante_R_D = Ka4D



		if Drehung == 90: #Neu 16.11.2022
			KantenVN, Kantencode = self.KantenCode(Ka1, Ka2, Ka3, Ka4, Ka1S, Ka2S, Ka3S, Ka4S, Ka1E, Ka2E, Ka3E, Ka4E, [3, 4, 2, 1])
			ExportBreite = Breite
			ExportLaenge = Laenge

			Kante_V = Ka3; Kante_V_D = Ka3D
			Kante_H = Ka4; Kante_H_D = Ka4D
			Kante_L = Ka2; Kante_L_D = Ka2D
			Kante_R = Ka1; Kante_R_D = Ka1D

		if Drehung == -180:
			KantenVN, Kantencode = self.KantenCode(Ka1, Ka2, Ka3, Ka4, Ka1S, Ka2S, Ka3S, Ka4S, Ka1E, Ka2E, Ka3E, Ka4E, [3, 4, 2, 1])
			ExportBreite = Breite
			ExportLaenge = Laenge

			Kante_V = Ka3; Kante_V_D = Ka3D
			Kante_H = Ka4; Kante_H_D = Ka4D
			Kante_L = Ka2; Kante_L_D = Ka2D
			Kante_R = Ka1; Kante_R_D = Ka1D

		Bemerkungen = self.asString(key='part_comment', **keywords)

		debug = str([Ka1+'_'+Ka1D, Ka2+'_'+Ka2D, Ka3+'_'+Ka3D, Ka4+'_'+Ka4D, Ka1S, Ka1E, Ka2S, Ka2E, Ka3S, Ka3E, Ka4S, Ka4E])
		#logging.error('debug')

		return (
			self.asString(data=projectInfo["ProjectID"], **keywords),  #Auftrag nicht verwendet beim Import
			Pos, #MUSS Zahl sein und MUSS sortiert sein. Also nicht pos 1, dann 2 dann wieder 1
			PosBeschreibung, #wird nicht verwendet
			Bauteil, #Bauteilbezeichnung oder Bauteilname
			Gruppe, #Möbelname, PosNr_Möbelname oder Positionsbezeichnung
			self.asString(data=entry.itemID, **keywords),
			self.asInt(data=entry.count, **keywords),
			ExportLaenge,
			ExportBreite,
			self.asCoordinate(data=entry.boardThickness, **keywords), #geändert 1.12.2020 vorher self.asCoordinate(data=entry.thickness, **keywords),
			Kante_V,
			Kante_V_D,
			Kante_H,
			Kante_H_D,
			Kante_L,
			Kante_L_D,
			Kante_R,
			Kante_R_D,
			self.asString(key='part_covering1', **keywords),
			self.asString(key='part_covering2', **keywords),
			Bemerkungen,
			Zumass,
			Kantencode,
			KantenVN,
			self.getNCProgramDisplayName(definition=self.NC_PROGRAM_DISPLAY_NAME_DEFINITION, data=entry.ncProgramPathMain, **keywords),
			self.getNCProgramDisplayName(definition=self.NC_PROGRAM_DISPLAY_NAME_DEFINITION, data=entry.ncProgramPathOpposite, **keywords),
			self.getNCProgramDisplayName(definition=self.NC_PROGRAM_DISPLAY_NAME_DEFINITION, data=entry.ncProgramPathSizing, **keywords),
			#debug,
			self.getGrain(entry.grain),
			ZumassNative,
			Ka1Zu,
			Ka2Zu,
			Ka3Zu,
			Ka4Zu,
			self.asString(key='part_laminate1', **keywords),
			self.asString(key='part_laminate2', **keywords),
			#self.getDataAsInt(key='part_constructiongroupcomponentid', **keywords),
			#self.getDataAsInt(key='part_constructiongroupid', **keywords),

		)



	def getLocalizedHeader(self, index, default):
		return getLocalizedString(CUTTINGLIST_RESOURCEGROUP, index, default)

	def doClipboardExport(self, **keywords):
		# Excel needs tabulators when pasting from clipboard (LibreOfficeCalc does not care, as it always shows the import dialog)
		self.csvdelimiter = '\t'
		super().doClipboardExport(**keywords)


export = SwissSoft()
export.doCuttinglistExport()
export.openExportPath()
