package mpd
import (
        "encoding/xml"
        "fmt"
        "strconv"
)
// ConditionalUint (ConditionalUintType) defined in XSD as a union of unsignedInt and boolean.
type ConditionalUint struct {
        u *uint64
        b *bool
}
// MarshalXMLAttr encodes ConditionalUint.
func (c ConditionalUint) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
        if c.u != nil {
                return xml.Attr{Name: name, Value: strconv.FormatUint(*c.u, 10)}, nil
        }
        if c.b != nil {
                return xml.Attr{Name: name, Value: strconv.FormatBool(*c.b)}, nil
        }
        // both are nil - no attribute, client will threat it like "false"
        return xml.Attr{}, nil
}
// UnmarshalXMLAttr decodes ConditionalUint.
func (c *ConditionalUint) UnmarshalXMLAttr(attr xml.Attr) error {
        u, err := strconv.ParseUint(attr.Value, 10, 64)
        if err == nil {
                c.u = &u
                return nil
        }
        b, err := strconv.ParseBool(attr.Value)
        if err == nil {
                c.b = &b
                return nil
        }
        return fmt.Errorf("ConditionalUint: can't UnmarshalXMLAttr %#v", attr)
}
// check interfaces
var (
        _ xml.MarshalerAttr   = ConditionalUint{}
        _ xml.UnmarshalerAttr = &ConditionalUint{}
)
		
		// Package mpd implements parsing and generating of MPEG-DASH Media Presentation Description (MPD) files.
package mpd
import (
        "bytes"
        "encoding/xml"
        "io"
        "regexp"
        "github.com/unki2aut/go-xsd-types"
)
// http://mpeg.chiariglione.org/standards/mpeg-dash
// https://www.brendanlong.com/the-structure-of-an-mpeg-dash-mpd.html
// http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd
var emptyElementRE = regexp.MustCompile(`></[A-Za-z]+>`)
// MPD represents root XML element.
type MPD struct {
        XMLNS                      *string       `xml:"xmlns,attr"`
        Type                       *string       `xml:"type,attr"`
        MinimumUpdatePeriod        *xsd.Duration `xml:"minimumUpdatePeriod,attr"`
        AvailabilityStartTime      *xsd.DateTime `xml:"availabilityStartTime,attr"`
        AvailabilityEndTime        *xsd.DateTime `xml:"availabilityEndTime,attr"`
        MediaPresentationDuration  *xsd.Duration `xml:"mediaPresentationDuration,attr"`
        MinBufferTime              *xsd.Duration `xml:"minBufferTime,attr"`
        SuggestedPresentationDelay *xsd.Duration `xml:"suggestedPresentationDelay,attr"`
        TimeShiftBufferDepth       *xsd.Duration `xml:"timeShiftBufferDepth,attr"`
        PublishTime                *xsd.DateTime `xml:"publishTime,attr"`
        Profiles                   string        `xml:"profiles,attr"`
        BaseURL                    []*BaseURL    `xml:"BaseURL,omitempty"`
        Period                     []*Period     `xml:"Period,omitempty"`
}
// Do not try to use encoding.TextMarshaler and encoding.TextUnmarshaler:
// https://github.com/golang/go/issues/6859#issuecomment-118890463
// Encode generates MPD XML.
func (m *MPD) Encode() ([]byte, error) {
        x := new(bytes.Buffer)
        e := xml.NewEncoder(x)
        e.Indent("", "  ")
        err := e.Encode(m)
        if err != nil {
                return nil, err
        }
        // hacks for self-closing tags
        res := new(bytes.Buffer)
        res.WriteString(`<?xml version="1.0" encoding="utf-8"?>`)
        res.WriteByte('\n')
        for {
                s, err := x.ReadString('\n')
                if s != "" {
                        s = emptyElementRE.ReplaceAllString(s, `/>`)
                        res.WriteString(s)
                }
                if err == io.EOF {
                        break
                }
                if err != nil {
                        return nil, err
                }
        }
        res.WriteByte('\n')
        return res.Bytes(), err
}
// Decode parses MPD XML.
func (m *MPD) Decode(b []byte) error {
        return xml.Unmarshal(b, m)
}
// Period represents XSD's PeriodType.
type Period struct {
        Start          *xsd.Duration    `xml:"start,attr"`
        ID             *string          `xml:"id,attr"`
        Duration       *xsd.Duration    `xml:"duration,attr"`
        AdaptationSets []*AdaptationSet `xml:"AdaptationSet,omitempty"`
        BaseURL        []*BaseURL       `xml:"BaseURL,omitempty"`
}
// BaseURL represents XSD's BaseURLType.
type BaseURL struct {
        Value                    string  `xml:",chardata"`
        ServiceLocation          *string `xml:"serviceLocation,attr"`
        ByteRange                *string `xml:"byteRange,attr"`
        AvailabilityTimeOffset   *uint64 `xml:"availabilityTimeOffset,attr"`
        AvailabilityTimeComplete *bool   `xml:"availabilityTimeComplete,attr"`
}
// AdaptationSet represents XSD's AdaptationSetType.
type AdaptationSet struct {
        MimeType                string           `xml:"mimeType,attr"`
        ContentType             *string          `xml:"contentType,attr"`
        SegmentAlignment        ConditionalUint  `xml:"segmentAlignment,attr"`
        SubsegmentAlignment     ConditionalUint  `xml:"subsegmentAlignment,attr"`
        StartWithSAP            ConditionalUint  `xml:"startWithSAP,attr"`
        SubsegmentStartsWithSAP ConditionalUint  `xml:"subsegmentStartsWithSAP,attr"`
        BitstreamSwitching      *bool            `xml:"bitstreamSwitching,attr"`
        Lang                    *string          `xml:"lang,attr"`
        Par                     *string          `xml:"par,attr"`
        Codecs                  *string          `xml:"codecs,attr"`
        Role                    []*Descriptor    `xml:"Role,omitempty"`
        BaseURL                 []*BaseURL       `xml:"BaseURL,omitempty"`
        SegmentTemplate         *SegmentTemplate `xml:"SegmentTemplate,omitempty"`
        ContentProtections      []Descriptor     `xml:"ContentProtection,omitempty"`
        Representations         []Representation `xml:"Representation,omitempty"`
}
// Representation represents XSD's RepresentationType.
type Representation struct {
        ID                 *string          `xml:"id,attr"`
        Width              *uint64          `xml:"width,attr"`
        Height             *uint64          `xml:"height,attr"`
        FrameRate          *string          `xml:"frameRate,attr"`
        Bandwidth          *uint64          `xml:"bandwidth,attr"`
        AudioSamplingRate  *string          `xml:"audioSamplingRate,attr"`
        Codecs             *string          `xml:"codecs,attr"`
        SAR                *string          `xml:"sar,attr"`
        ScanType           *string          `xml:"scanType,attr"`
        ContentProtections []Descriptor     `xml:"ContentProtection,omitempty"`
        SegmentTemplate    *SegmentTemplate `xml:"SegmentTemplate,omitempty"`
        BaseURL            []*BaseURL       `xml:"BaseURL,omitempty"`
}
// Descriptor represents XSD's DescriptorType.
type Descriptor struct {
        SchemeIDURI      *string `xml:"schemeIdUri,attr"`
        Value            *string `xml:"value,attr"`
        CencDefaultKeyId *string `xml:"cenc:default_KID,attr,omitempty"`
        MSPRPro          *string `xml:"mspr:pro,omitempty"`
        CencPSSH         *string `xml:"cenc:pssh,omitempty"`
}
// SegmentTemplate represents XSD's SegmentTemplateType.
type SegmentTemplate struct {
        Duration               *uint64          `xml:"duration,attr"`
        Timescale              *uint64          `xml:"timescale,attr"`
        Media                  *string          `xml:"media,attr"`
        Initialization         *string          `xml:"initialization,attr"`
        StartNumber            *uint64          `xml:"startNumber,attr"`
        PresentationTimeOffset *uint64          `xml:"presentationTimeOffset,attr"`
        SegmentTimeline        *SegmentTimeline `xml:"SegmentTimeline,omitempty"`
}
// SegmentTimeline represents XSD's SegmentTimelineType.
type SegmentTimeline struct {
        S []*SegmentTimelineS `xml:"S"`
}
// SegmentTimelineS represents XSD's SegmentTimelineType's inner S elements.
type SegmentTimelineS struct {
        T *uint64 `xml:"t,attr"`
        D uint64  `xml:"d,attr"`
        R *int64  `xml:"r,attr"`
}