# -*- 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 interiorcad.backend.exportsettingsfile
# import interiorcad.interface.configurationkeys as ConfigurationKeys
from interiorcad.interface.geometry.edges import EdgeData
from interiorcad.backend.dosfilenamecreator import DosFilenameCreator
import re

import sys


class Triviso_SL_Export(CuttinglistExportCSVBase):
    def __init__(self, **keywords):
        super().__init__(**keywords)
        self.csvdelimiter = ';'
        self.EXTENSION = 'csv'
        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.CUMULATE_COVERINGS = self.getCuttinglistConfiguration().getAsBool('cumulate-coverings', False)
        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.EXPORT_FORMAT = 'Triviso'
        self.Produktionsprozess_Standard = self.getCuttinglistConfiguration().get('1. Produktionsprozess Standard', '2')

        self.Produktionsprozess = '7' #um alte Einstellungen abzufangen 
        self.Produktionsprozess_keywords = self.getCuttinglistConfiguration().get('2. Produktionsprozess Keywort Filter',
                                                                         'rück travers')

        self.Produktionsprozess_from_keywords = self.getCuttinglistConfiguration().get('3. Produktionsprozess für Filter',
                                                                         'Filter nicht berücksichtigen')

        self.Produktionsprozess_use_comment = self.getCuttinglistConfiguration().get('4. Produktionsprozess Bemerkungen berücksichtigen',
                                                                         False)

        self.SHORT_PART_NAMES = self.getCuttinglistConfiguration().getAsBool('short-part-names', False)
        self.KantenReihenfolge = self.getCuttinglistConfiguration().get('Triviso Kantenreihenfolge', 'interiorcad')
        self.TrivisoPosition = self.getCuttinglistConfiguration().get('Spalte Position', '1')
        self.TrivisoPosBezeichnung = self.getCuttinglistConfiguration().get('Spalte PosBezeichnung', '1')
        self.TrivisoGruppe = self.getCuttinglistConfiguration().get('Spalte Baugruppe', '1')
        self.TrivisoBezeichnung = self.getCuttinglistConfiguration().get('Spalte Bezeichnung', '1')
        self.TrivisoGruppeID = self.getCuttinglistConfiguration().get('Spalte Baugruppe ID', '2')
        self.GruppenNr = []
        self.Gruppen = []
        self.counter = 0
        self.elements = []

    def getDecimalSeparator(self, **keywords):
        return '.'
    '''  
    def getDataFrom(self, column, keywords):
        entry = keywords['entry']
        data = column  #column.data #original function nutzt column.data

        return self.FIELD_TO_VALUE[data](entry, column, keywords, self)    
        '''
    '''update 24.10.2024'''
    def extract_and_remove_first_number(self, s):
        match = re.match(r'^(\d+)(.*)', s)
        if match:
            number = match.group(1)
            remaining_string = match.group(2).strip()
            return remaining_string, number
        else:
            return s, None

    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 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',
                'Typ_V', 'Typ_H', 'Typ_L', 'Typ_R', 'Ecke_OR', 'Ecke_RU', 'Ecke_UL', 'Ecke_LO',
                'Dicke_BA', 'Dicke_BI', 'Oberfl_A', 'Oberfl_I', 'Barcode_A', 'Barcode_I',
                'Bearb_Prozess', 'Multiplikator', 'Baugruppe_Unique_ID')



    def EdgeTranslate(self, **keywords):
        entry = keywords['entry']
        EdgeDict = {'Discontinuous': '1', 'Continuous': '2', 'Miter': '3', '': '0'}

        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))

        OR = EdgeDict.get(Ka2S)
        RU = EdgeDict.get(Ka2E)
        UL = EdgeDict.get(Ka1S)
        LO = EdgeDict.get(Ka1E)

        KantenStoesse = [OR, RU, UL, LO]

        return KantenStoesse

    def getElements(self, **keywords):
        self.counter += 1
        entry = keywords['entry']
        projectInfo = keywords['projectInfo']
        positionInfo = keywords['positionInfo']
        workpiece = keywords['workpiece']
        Moebelname = self.asString(data=positionInfo["CabinetName"], **keywords)
        PosNr = self.asString(data=positionInfo["PositionNumber"], **keywords)
        PosBez = self.asString(data=positionInfo["PositionDescription"], **keywords)


        Position = ''
        PosBezeichnung = ''
        Baugruppe = ''
        Bezeichnung = ''

        BauteilName = self.asString(key='unit_unitid', **keywords)
        # edit 7.8.2024 dc soll kumulierten Bauteilnamen generieren
        BauteilName = self.asString(data=entry.name, **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


        # Spalte Position
        if self.TrivisoPosition == '1':
            Position = self.counter  # fortlaufende Nummer

        # Spalte C Pos.Bezeichnung (ähnliche Wie E)
        # Zwei ähnliche3 Spalten, eine für die Bezeichnung, die anderen für den Namen. Aber es wird unterschliedlich benötigt aus Kulturellen gründen.
        if self.TrivisoPosBezeichnung == '1':  # Nummer + Bauteil Name (Standard)
            PosBezeichnung = str(self.counter) + '_' + BauteilName  # Nummber + Name
        if self.TrivisoPosBezeichnung == '2':  # Bauteil Name
            PosBezeichnung = BauteilName  # Bauteil Name
        if self.TrivisoPosBezeichnung == '3':  # Bauteil Bezeichnung
            PosBezeichnung = BauteilBez  # Bauteil Bezeichnung
        if self.TrivisoPosBezeichnung == '4':  # Bezeichnung oder Name, falls Bezeichnung fehlt
            PosBezeichnung = BauteilBez if BauteilBez else BauteilName


        if PosNr and PosBez:
            PosNr_PosBez  = f'{PosNr}-{PosBez}'
        else:
            PosNr_PosBez = PosNr or PosBez or ''


        merged_all = PosNr_PosBez or Moebelname or 'nicht zugewiesen' 
        merged_without_pos_number = PosBez or Moebelname or 'nicht zugewiesen'

        # Spalte D Baugruppe
        if self.TrivisoGruppe == '1': #Automatisch - Standard #PosNr-PostBez sonst Möbel sinst n.zugew.
            Baugruppe = merged_all
        if self.TrivisoGruppe == '4': #Automatisch - ohne Positions Nummer
            Baugruppe = PosBez or PosNr or merged_without_pos_number  # +'-'+Gruppe
        if self.TrivisoGruppe == '2':
            Baugruppe = PosNr or '999'
        if self.TrivisoGruppe == '3':
            s_temp = f'{PosNr or "999"}-{PosBez or "nicht zugewiesen"}'
            Baugruppe = s_temp
            

    

        # Spalte Bezeichnung
        # Spalte E Bezeichnung
        if self.TrivisoBezeichnung == '1':
            Bezeichnung = BauteilName  # Bauteil Name
        if self.TrivisoBezeichnung == '2':
            Bezeichnung = BauteilBez  # Bauteil Bezeichnung
        if self.TrivisoBezeichnung == '3':
            Bezeichnung = str(self.counter) + '_' + BauteilName  # Nummber + Name
        if self.TrivisoBezeichnung == '4':  # Bauteil Name Kurz (18.9.2020 dom)
            Bezeichnung = BauteilBez if BauteilBez else BauteilName

        # Spalte AI Baugruppe Unique ID
        if self.TrivisoGruppeID == '1': #Automatisch - Standard #PosNr-PostBez sonst Möbel sinst n.zugew.
            BaugruppeID = merged_all
        if self.TrivisoGruppeID == '4': #Automatisch - ohne Positions Nummer
            BaugruppeID = PosBez or PosNr or merged_without_pos_number  # +'-'+Gruppe
        if self.TrivisoGruppeID == '2':
            BaugruppeID = PosNr or '999'
        if self.TrivisoGruppeID == '3':
            s_temp = f'{PosNr or "999"}-{PosBez or "nicht zugewiesen"}'
            
            BaugruppeID = s_temp
            
        #alte Optionen 2022 entweder oder
        if self.Produktionsprozess != '7':
            if self.Produktionsprozess in ['5' or "self.asString(key='part_comment', **keywords)"]:               
                Produktionsprozess = self.asString(key='part_comment', **keywords)
            else:
                Produktionsprozess = self.Produktionsprozess
                                
        # neue Optionen 2023 Produktionsprozess, Priorität 1. Kommentar, 2. Filter, 3. Standard
        else: #neue Optionen verwenden
            Produktionsprozess = self.Produktionsprozess_Standard
            if self.Produktionsprozess_keywords != '5': #Suchwörter in Bateilbezeichnung
                filter_parts = re.split('\\s+', self.Produktionsprozess_keywords)
                filter_parts.append('dummy')

                for s in filter_parts:
                    if s in self.asString(key='part_description', **keywords).lower() or s in self.asString(key='unit_unitid', **keywords).lower(): #wenn Suchwort gefunden, dann Produktionsprozess für Filter
                        Produktionsprozess = self.Produktionsprozess_from_keywords
                        break
            if self.Produktionsprozess_use_comment:

                part_comment = self.asString(key='part_comment', **keywords)
                bemerkung_ohne_zahl, anfang_zahl_bemerkungen = self.extract_and_remove_first_number(part_comment)   

                if  anfang_zahl_bemerkungen != None: # Wenn Bemerkungen übernehmen True und nur dann, wenn Bemerkung eine Zahl ist.
                    Produktionsprozess = anfang_zahl_bemerkungen
                    bemerkungen = bemerkung_ohne_zahl

                else:
                    bemerkungen = self.asString(key='part_comment', **keywords)

            else:
                bemerkungen = self.asString(key='part_comment', **keywords)
                   

        if entry.isFitting():
            Bezeichnung = BauteilBez  # Bauteil Bezeichnung

        Kantenstoesse = self.EdgeTranslate(**keywords)

        return (
            self.asString(data=projectInfo["ProjectID"], **keywords),  # Auftrag nicht verwendet beim Import
            Position,  # wird in Spalte Position geschrieben
            PosBezeichnung,  # wird in Spalte Pos. Bezeichnung geschrieben
            Baugruppe,    
            # Pos+PosBez oder Möbelname oder Bauteilname Bildet Bei Triviso wahlweise Bezeichnung (empfohlen) oder Kennung.
            Bezeichnung,  # Bauteilbezeichnung oder Name
            self.asString(key='part_itemid', **keywords),  # Artikelnummer (Material)
            self.asInt(data=entry.count, **keywords),
            self.asCoordinate(data=entry.boardLengthGrainDirection, **keywords),
            # Format gemäss Exporteinstellung, Länge (Triviso Kantenbild Senkrechte)
            self.asCoordinate(data=entry.boardWidthGrainDirection, **keywords),
            # Format gemäss Exporteinstellung Breite (Triviso Kantenbild Horizontal)
            self.asCoordinate(data=entry.boardThickness, **keywords),
            # Wird zusammen mit Artikel in Triviso als Importartikel eingelesen
            self.asString(data=entry.edgesGrainDirection.right.supplierID, **keywords),
            # Kante 4 Breitseite (Triviso immer oben)
            self.asCoordinate(data=entry.edgesGrainDirection.right.thickness, **keywords),
            self.asString(data=entry.edgesGrainDirection.left.supplierID, **keywords),
            # Kante 3 Breitseite (Triviso immer unten)
            self.asCoordinate(data=entry.edgesGrainDirection.left.thickness, **keywords),
            self.asString(data=entry.edgesGrainDirection.front.supplierID, **keywords),
            # Kante 1 immer Längsseite, Triviso Kantenbild rechts # Kanten 1=Tr_rechts, 2=Tr_links, 3=Tr_unten, 4=Tr_oben
            self.asCoordinate(data=entry.edgesGrainDirection.front.thickness, **keywords),
            self.asString(data=entry.edgesGrainDirection.back.supplierID, **keywords),
            # Kante 2 immer gegenüber Kante 1
            self.asCoordinate(data=entry.edgesGrainDirection.back.thickness, **keywords),
            self.asString(key='part_covering1', **keywords),
            self.asString(key='part_covering2', **keywords),
            bemerkungen, # edit 6.8.2024 self.asString(key='part_comment', **keywords),
            '2',  # 'Typ_V', 0 ohne, 1 vor Belag, 2 nach Belag
            '2',  # 'Typ_H',
            '2',  # 'Typ_L',
            '2',  # Typ_R',
            Kantenstoesse[0],  # 'Ecke_OR',Triviso 2=durchgehend Länge, 1=durchgehend Breite, 3=Gehrung
            Kantenstoesse[1],  # 'Ecke_RU',
            Kantenstoesse[2],  # 'Ecke_UL',
            Kantenstoesse[3],  # 'Ecke_LO',
            self.asCoordinate(key='part_covering2thickness', **keywords),
            self.asCoordinate(key='part_covering1thickness', **keywords),
            self.asString(key='part_laminate2', **keywords),  # Beschichtung
            self.asString(key='part_laminate1', **keywords),  # Beschichtung
            self.getNCProgramDisplayName(definition=self.NC_PROGRAM_DISPLAY_NAME_DEFINITION, data=entry.ncProgramPathOpposite, **keywords),  # Dateipfad CNC Nebenseite
            self.getNCProgramDisplayName(definition=self.NC_PROGRAM_DISPLAY_NAME_DEFINITION, data=entry.ncProgramPathMain, **keywords),  # Dateipfad CNC Hauptseite
            Produktionsprozess,
            # Zugabenregelung ERP je nach Kunde unterschiedlich 2 ist oft Beschichtete Platte (muss nicht ausgegeben werden -> Regelt Zumasse, Zuschnittmasse etc.)
            '',  # Multiplikator
            BaugruppeID,
        # Baugruppe_Unique_ID,#Unique_ID bei Möbelexport verwendet, Ebenfalls als Bezeichnung/Möbelname der Stückliste (Baugruppe, Erfassungsgruppe), falls Importeinstellung entsprechend
        )

    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 = Triviso_SL_Export()
export.doCuttinglistExport()
export.openExportPath()
