from .envelope import InterchangeEnvelope
from .segment import Segment
from .element import Element
from .errors import IDMismatchError, SegmentCountError


class Interchange(InterchangeEnvelope):
    """An EDI X12 interchange"""

    def __init__(self):
        InterchangeEnvelope.__init__(self)
        self.header = InterchangeHeader()
        self.trailer = InterchangeTrailer()

    def validate(self, report):
        """
        Validate the envelope
        :param report: the validation report to append errors.
        """
        super(InterchangeEnvelope, self).validate(report)
        self.__validate_control_ids(report)
        self.__validate_group_count(report)

    def __validate_control_ids(self, report):
        """
        Validate the control id match in the header and trailer
        :param report: the validation report to append errors.
        """
        if self.header.isa13.content != self.trailer.iea02.content:
            isa13_desc = self.header.isa13.description
            isa13_name = self.header.isa13.name
            iea02_desc = self.trailer.iea02.description
            iea02_name = self.trailer.iea02.name
            report.add_error(IDMismatchError(
                msg="The " + isa13_desc + " in " + isa13_name + " does not match " + iea02_desc + " in " + iea02_name,
                segment=self.header.id))

    def __validate_group_count(self, report):
        """
        Validate the actual group count matches the specified count.
        :param report: the validation report to append errors.
        """
        if int(self.trailer.iea01.content) != len(self.groups):
            report.add_error(SegmentCountError(
                msg="The " + self.trailer.iea01.description + " in " + self.trailer.iea01.name +
                    " value of " + self.trailer.iea01.content + " does not match the parsed count of " +
                    str(len(self.groups)),
                segment=self.trailer.id))

    def __repr__(self):
        return f"""
            Interchange(
                Header => {self.header}
                Trailer => {self.trailer}
                Body => {self.body}
                Groups => {self.groups}
            )
        """


class InterchangeHeader(Segment):
    """An EDI X12 interchange header"""

    def __init__(self):
        Segment.__init__(self)
        self.fieldCount = 16

        self.id = Element(name="ISA",
                          description="Interchange Control Header Code",
                          required=True, min_length=3, max_length=3, content="ISA")
        self.fields.append(self.id)

        self.isa01 = Element(name="ISA01",
                             description="Authorization Information Qualifier",
                             required=True, min_length=2, max_length=2, content="")
        self.fields.append(self.isa01)

        self.isa02 = Element(name="ISA02",
                             description="Authorization Information",
                             required=True, min_length=10, max_length=10, content="")
        self.fields.append(self.isa02)

        self.isa03 = Element(name="ISA03",
                             description="Security Information Qualifier",
                             required=True, min_length=2, max_length=2, content="")
        self.fields.append(self.isa03)

        self.isa04 = Element(name="ISA04",
                             description="Security Information",
                             required=True, min_length=10, max_length=10, content="")
        self.fields.append(self.isa04)

        self.isa05 = Element(name="ISA05",
                             description="Interchange ID Qualifier",
                             required=True, min_length=2, max_length=2, content="")
        self.fields.append(self.isa05)

        self.isa06 = Element(name="ISA06",
                             description="Interchange Sender ID",
                             required=True, min_length=15, max_length=15, content="")
        self.fields.append(self.isa06)

        self.isa07 = Element(name="ISA07",
                             description="Interchange ID Qualifier",
                             required=True, min_length=2, max_length=2, content="")
        self.fields.append(self.isa07)

        self.isa08 = Element(name="ISA08",
                             description="Interchange Receiver ID",
                             required=True, min_length=15, max_length=15, content="")
        self.fields.append(self.isa08)

        self.isa09 = Element(name="ISA09",
                             description="Interchange Date",
                             required=True, min_length=6, max_length=6, content="")
        self.fields.append(self.isa09)

        self.isa10 = Element(name="ISA10",
                             description="Interchange Time",
                             required=True, min_length=4, max_length=4, content="")
        self.fields.append(self.isa10)

        self.isa11 = Element(name="ISA11",
                             description="Interchange Control Standard ID",
                             required=True, min_length=1, max_length=1, content="")
        self.fields.append(self.isa11)

        self.isa12 = Element(name="ISA12",
                             description="Interchange Control Version Number",
                             required=True, min_length=5, max_length=5, content="")
        self.fields.append(self.isa12)

        self.isa13 = Element(name="ISA13",
                             description="Interchange Control Number",
                             required=True, min_length=9, max_length=9, content="")
        self.fields.append(self.isa13)

        self.isa14 = Element(name="ISA14",
                             description="Acknowledgement Requested Flag",
                             required=True, min_length=1, max_length=1, content="")
        self.fields.append(self.isa14)

        self.isa15 = Element(name="ISA15",
                             description="Test Indicator",
                             required=True, min_length=1, max_length=1, content="")
        self.fields.append(self.isa15)

        self.isa16 = Element(name="ISA16",
                             description="Sub-element Separator",
                             required=True, min_length=1, max_length=1, content="")
        self.fields.append(self.isa16)

    def __repr__(self):
        return f"""
                InterchangeHeader(
                    Field Count => {self.fieldCount}
                    Fields => {[val.content for val in self.fields]}
                    Element Separator => {self.element_separator}
                    Segment Terminator => {self.segment_terminator}
                    Sub Element Separator => {self.sub_element_separator}
                    ISA01 => {self.isa01}
                    ISA02 => {self.isa02}
                    ISA03 => {self.isa03}
                    ISA04 => {self.isa04}
                    ISA05 => {self.isa05}
                    ISA06 => {self.isa06}
                    ISA07 => {self.isa07}
                    ISA08 => {self.isa08}
                    ISA09 => {self.isa09}
                    ISA10 => {self.isa10}
                    ISA11 => {self.isa11}
                    ISA12 => {self.isa12}
                    ISA13 => {self.isa13}
                    ISA14 => {self.isa14}
                    ISA15 => {self.isa15}
                    ISA16 => {self.isa16}
                )
        """


class InterchangeTrailer(Segment):
    """An EDI X12 interchange Trailer"""

    def __init__(self):
        Segment.__init__(self)
        self.fieldCount = 2

        self.id = Element(name="IEA",
                          description="Interchange Control Trailer Code",
                          required=True, min_length=3, max_length=3, content="")
        self.fields.append(self.id)

        self.iea01 = Element(name="IEA01",
                             description="Number of Included Groups",
                             required=True, min_length=1, max_length=5, content="")
        self.fields.append(self.iea01)

        self.iea02 = Element(name="IEA02",
                             description="Interchange Control Number",
                             required=True, min_length=1, max_length=9, content="")
        self.fields.append(self.iea02)

    def __repr__(self):
        return f"""
                InterchangeTrailer(
                    Field Count => {self.fieldCount}
                    Fields => {[val.content for val in self.fields]}
                    Element Separator => {self.element_separator}
                    Segment Terminator => {self.segment_terminator}
                    Sub Element Separator => {self.sub_element_separator}
                    IEA01 => {self.iea01}
                    IEA02 => {self.iea02}
                )
        """