from autosar.base import parseXMLFile,splitRef,parseTextNode,parseIntNode,hasAdminData,parseAdminDataNode
from autosar.system import *
from autosar.parser.parser_base import ElementParser

class SystemParser(ElementParser):
    def __init__(self,version=3.0):
        super().__init__(version)

    def getSupportedTags(self):
        return ['SYSTEM']

    def parseElement(self, xmlElement, parent = None):
        if xmlElement.tag == 'SYSTEM':
            return self.parseSystem(xmlElement, parent)
        else:
            return None

    def parseSystem(self,xmlRoot,parent=None):
        """
        parses <SYSTEM>
        """
        assert(xmlRoot.tag=='SYSTEM')
        xmlName = xmlRoot.find('SHORT-NAME')
        if xmlName is not None:
            system=System(parseTextNode(xmlName),parent)
            for xmlElem in xmlRoot.findall('./*'):
                if xmlElem.tag=='SHORT-NAME':
                    pass
                elif xmlElem.tag=='ADMIN-DATA':
                    system.adminData=parseAdminDataNode(xmlElem)
                elif xmlElem.tag=='FIBEX-ELEMENT-REFS':
                    self.parseFibexElementRefs(xmlElem,system)
                elif xmlElem.tag=='MAPPING':
                    self.parseSystemMapping(xmlElem,system)
                elif xmlElem.tag=='SOFTWARE-COMPOSITION':
                    self.parseSoftwareComposition(xmlElem,system)
                else:
                    raise NotImplementedError(xmlElem.tag)
            return system
        else:
            raise KeyError('expected to find <SHORT-NAME> inside <SYSTEM> tag')

    def parseFibexElementRefs(self,xmlRoot,system):
        for xmlElem in xmlRoot.findall('./*'):
            if xmlElem.tag=='FIBEX-ELEMENT-REF':
                system.fibexElementRefs.append(parseTextNode(xmlElem))
            else:
                raise NotImplementedError(xmlElem.tag)

    def parseSystemMapping(self,xmlRoot,system):
        """parses <MAPPING>"""
        assert(xmlRoot.tag=='MAPPING')
        name=parseTextNode(xmlRoot.find('SHORT-NAME'))
        system.mapping = Mapping(name,system)
        for xmlElem in xmlRoot.findall('./*'):
            if xmlElem.tag=='SHORT-NAME':
                pass
            elif xmlElem.tag=='DATA-MAPPINGS':
                self.parseDataMapping(xmlElem,system.mapping.data)
            elif xmlElem.tag=='SW-IMPL-MAPPINGS':
                self.parseSwImplMapping(xmlElem,system.mapping)
            elif xmlElem.tag=='SW-MAPPINGS':
                self.parseSwMapping(xmlElem,system.mapping)
            else:
                raise NotImplementedError(xmlElem.tag)

    def parseDataMapping(self,xmlRoot,dataMapping):
        """parses <DATA-MAPPINGS>"""
        assert(xmlRoot.tag=='DATA-MAPPINGS')
        for xmlElem in xmlRoot.findall('./*'):
            if xmlElem.tag=='SWC-TO-IMPL-MAPPING':
                pass
            elif xmlElem.tag=='SENDER-RECEIVER-TO-SIGNAL-MAPPING':
                dataMapping.senderReceiverToSignal.append(self.parseSenderReceiverToSignalMapping(xmlElem))
            elif xmlElem.tag=='SENDER-RECEIVER-TO-SIGNAL-GROUP-MAPPING':
                dataMapping.senderReceiverToSignalGroup.append(self.parseSenderReceiverToSignalGroupMapping(xmlElem))
            else:
                raise NotImplementedError(xmlElem.tag)

    def parseSwImplMapping(self,xmlRoot,mapping):
        """parses <SW-IMPL-MAPPINGS>"""
        assert(xmlRoot.tag=='SW-IMPL-MAPPINGS')
        for xmlElem in xmlRoot.findall('./*'):
            if xmlElem.tag=='SWC-TO-IMPL-MAPPING':
                pass
            else:
                raise NotImplementedError(xmlElem.tag)

    def parseSwMapping(self,xmlRoot,mapping):
        """parses <SW-MAPPINGS>"""
        assert(xmlRoot.tag=='SW-MAPPINGS')
        for xmlElem in xmlRoot.findall('./*'):
            if xmlElem.tag=='SWC-TO-ECU-MAPPING':
                pass
            else:
                raise NotImplementedError(xmlElem.tag)

    def parseSoftwareComposition(self,xmlRoot,system):
        """parses <SOFTWARE-COMPOSITION>"""
        assert(xmlRoot.tag=='SOFTWARE-COMPOSITION')
        name=parseTextNode(xmlRoot.find('SHORT-NAME'))
        for xmlElem in xmlRoot.findall('./*'):
            if xmlElem.tag=='SHORT-NAME':
                pass
            elif xmlElem.tag=='SOFTWARE-COMPOSITION-TREF':
                pass
            else:
                raise NotImplementedError(xmlElem.tag)

    def parseSenderReceiverToSignalMapping(self,xmlRoot):
        """parses <'SENDER-RECEIVER-TO-SIGNAL-MAPPING'>"""
        assert(xmlRoot.tag=='SENDER-RECEIVER-TO-SIGNAL-MAPPING')
        dataElemIRef=None
        signalRef=None
        for xmlElem in xmlRoot.findall('./*'):
            if xmlElem.tag=='DATA-ELEMENT-IREF':
                dataElemIRef=self.parseDataElemInstanceRef(xmlElem)
            elif xmlElem.tag=='SIGNAL-REF':
                signalRef=parseTextNode(xmlElem)
            else:
                raise NotImplementedError(xmlElem.tag)
        if (dataElemIRef is not None) and (signalRef is not None):
            return SenderReceiverToSignalMapping(dataElemIRef,signalRef)
        else:
            raise Exception("failed to parse SENDER-RECEIVER-TO-SIGNAL-MAPPING")

    def parseSenderReceiverToSignalGroupMapping(self,xmlRoot):
        """parses <'SENDER-RECEIVER-TO-SIGNAL-GROUP-MAPPING'>"""
        assert(xmlRoot.tag=='SENDER-RECEIVER-TO-SIGNAL-GROUP-MAPPING')
        dataElemIRef=None
        signalGroupRef=None
        typeMapping=None
        for xmlElem in xmlRoot.findall('./*'):
            if xmlElem.tag == 'DATA-ELEMENT-IREF': #minOccurs=0, maxOccurs=1
                dataElemIRef=self.parseDataElemInstanceRef(xmlElem)
            elif xmlElem.tag == 'SIGNAL-GROUP-REF': #minOccurs=0, maxOccurs=
                signalGroupRef=parseTextNode(xmlElem)
            elif xmlElem.tag == 'TYPE-MAPPING': #minOccurs=0, maxOccurs=1
                for xmlChild in xmlElem.findall('./*'):
                    if xmlChild.tag=='SENDER-REC-ARRAY-TYPE-MAPPING':
                        typeMapping = ArrayElementMapping()
                        for xmlItem in xmlChild.findall('./ARRAY-ELEMENT-MAPPINGS/SENDER-REC-ARRAY-TYPE-MAPPING'):
                            print("SENDER-REC-ARRAY-TYPE-MAPPING not implemented")
                    elif xmlChild.tag=='SENDER-REC-RECORD-TYPE-MAPPING':
                        typeMapping=RecordElementMapping()
                        for xmlItem in xmlChild.findall('./RECORD-ELEMENT-MAPPINGS/SENDER-REC-RECORD-ELEMENT-MAPPING'):
                            typeMapping.elements.append(self.parseSenderRecRecordElementMapping(xmlItem))
                    else:
                        raise NotImplementedError(xmlChild.tag)
            else:
                raise NotImplementedError(xmlElem.tag)
        return SenderReceiverToSignalGroupMapping(dataElemIRef,signalGroupRef,typeMapping)

    def parseDataElemInstanceRef(self,xmlRoot):
        dataElemRef=parseTextNode(xmlRoot.find('DATA-ELEMENT-REF'))
        assert(dataElemRef is not None)
        dataElemIRef=SignalDataElementInstanceRef(dataElemRef)
        for xmlChild in xmlRoot.findall('./*'):
            if xmlChild.tag=='DATA-ELEMENT-REF':
                pass
            elif xmlChild.tag=='SOFTWARE-COMPOSITION-REF':
                dataElemIRef.softwareCompositionRef=parseTextNode(xmlChild)
            elif xmlChild.tag=='COMPONENT-PROTOTYPE-REF':
                dataElemIRef.componentPrototypeRef.append(parseTextNode(xmlChild))
            elif xmlChild.tag=='PORT-PROTOTYPE-REF':
                dataElemIRef.portPrototypeRef=parseTextNode(xmlChild)
            else:
                raise NotImplementedError(xmlChild.tag)
        return dataElemIRef

    def parseSenderRecRecordElementMapping(self,xmlRoot):
        """parses <'SENDER-REC-RECORD-ELEMENT-MAPPING'>"""
        assert(xmlRoot.tag=='SENDER-REC-RECORD-ELEMENT-MAPPING')
        recordElementRef=None
        signalRef=None
        for xmlElem in xmlRoot.findall('./*'):
            if xmlElem.tag=='RECORD-ELEMENT-REF': #minOccurs="0" maxOccurs="1"
                recordElementRef=parseTextNode(xmlElem)
            elif xmlElem.tag=='SIGNAL-REF': #minOccurs="0" maxOccurs="1"
                signalRef=parseTextNode(xmlElem)
            else:
                raise NotImplementedError(xmlElem.tag)
        return SenderRecRecordElementMapping(recordElementRef,signalRef)

    def parseSenderRecArrayElementMapping(self,xmlRoot):
        """parses <'SENDER-REC-RECORD-ELEMENT-MAPPING'>"""
        assert(xmlRoot.tag=='SENDER-REC-RECORD-ELEMENT-MAPPING')
        raise NotImplementedError(xmlRoot.tag)
