package sml

import (
	"encoding/xml"

	"go.devnw.com/ooxml"
)

type CT_Stylesheet struct {
	// Number Formats
	NumFmts *CT_NumFmts
	// Fonts
	Fonts *CT_Fonts
	// Fills
	Fills *CT_Fills
	// Borders
	Borders *CT_Borders
	// Formatting Records
	CellStyleXfs *CT_CellStyleXfs
	// Cell Formats
	CellXfs *CT_CellXfs
	// Cell Styles
	CellStyles *CT_CellStyles
	// Formats
	Dxfs *CT_Dxfs
	// Table Styles
	TableStyles *CT_TableStyles
	// Colors
	Colors *CT_Colors
	// Future Feature Data Storage Area
	ExtLst *CT_ExtensionList
}

func NewCT_Stylesheet() *CT_Stylesheet {
	ret := &CT_Stylesheet{}
	return ret
}

func (m *CT_Stylesheet) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	e.EncodeToken(start)
	if m.NumFmts != nil {
		senumFmts := xml.StartElement{Name: xml.Name{Local: "ma:numFmts"}}
		e.EncodeElement(m.NumFmts, senumFmts)
	}
	if m.Fonts != nil {
		sefonts := xml.StartElement{Name: xml.Name{Local: "ma:fonts"}}
		e.EncodeElement(m.Fonts, sefonts)
	}
	if m.Fills != nil {
		sefills := xml.StartElement{Name: xml.Name{Local: "ma:fills"}}
		e.EncodeElement(m.Fills, sefills)
	}
	if m.Borders != nil {
		seborders := xml.StartElement{Name: xml.Name{Local: "ma:borders"}}
		e.EncodeElement(m.Borders, seborders)
	}
	if m.CellStyleXfs != nil {
		secellStyleXfs := xml.StartElement{Name: xml.Name{Local: "ma:cellStyleXfs"}}
		e.EncodeElement(m.CellStyleXfs, secellStyleXfs)
	}
	if m.CellXfs != nil {
		secellXfs := xml.StartElement{Name: xml.Name{Local: "ma:cellXfs"}}
		e.EncodeElement(m.CellXfs, secellXfs)
	}
	if m.CellStyles != nil {
		secellStyles := xml.StartElement{Name: xml.Name{Local: "ma:cellStyles"}}
		e.EncodeElement(m.CellStyles, secellStyles)
	}
	if m.Dxfs != nil {
		sedxfs := xml.StartElement{Name: xml.Name{Local: "ma:dxfs"}}
		e.EncodeElement(m.Dxfs, sedxfs)
	}
	if m.TableStyles != nil {
		setableStyles := xml.StartElement{Name: xml.Name{Local: "ma:tableStyles"}}
		e.EncodeElement(m.TableStyles, setableStyles)
	}
	if m.Colors != nil {
		secolors := xml.StartElement{Name: xml.Name{Local: "ma:colors"}}
		e.EncodeElement(m.Colors, secolors)
	}
	if m.ExtLst != nil {
		seextLst := xml.StartElement{Name: xml.Name{Local: "ma:extLst"}}
		e.EncodeElement(m.ExtLst, seextLst)
	}
	e.EncodeToken(xml.EndElement{Name: start.Name})
	return nil
}

func (m *CT_Stylesheet) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	// initialize to default
lCT_Stylesheet:
	for {
		tok, err := d.Token()
		if err != nil {
			return err
		}
		switch el := tok.(type) {
		case xml.StartElement:
			switch el.Name {
			case xml.Name{Space: "http://schemas.openxmlformats.org/spreadsheetml/2006/main", Local: "numFmts"},
				xml.Name{Space: "http://purl.oclc.org/ooxml/spreadsheetml/main", Local: "numFmts"}:
				m.NumFmts = NewCT_NumFmts()
				if err := d.DecodeElement(m.NumFmts, &el); err != nil {
					return err
				}
			case xml.Name{Space: "http://schemas.openxmlformats.org/spreadsheetml/2006/main", Local: "fonts"},
				xml.Name{Space: "http://purl.oclc.org/ooxml/spreadsheetml/main", Local: "fonts"}:
				m.Fonts = NewCT_Fonts()
				if err := d.DecodeElement(m.Fonts, &el); err != nil {
					return err
				}
			case xml.Name{Space: "http://schemas.openxmlformats.org/spreadsheetml/2006/main", Local: "fills"},
				xml.Name{Space: "http://purl.oclc.org/ooxml/spreadsheetml/main", Local: "fills"}:
				m.Fills = NewCT_Fills()
				if err := d.DecodeElement(m.Fills, &el); err != nil {
					return err
				}
			case xml.Name{Space: "http://schemas.openxmlformats.org/spreadsheetml/2006/main", Local: "borders"},
				xml.Name{Space: "http://purl.oclc.org/ooxml/spreadsheetml/main", Local: "borders"}:
				m.Borders = NewCT_Borders()
				if err := d.DecodeElement(m.Borders, &el); err != nil {
					return err
				}
			case xml.Name{Space: "http://schemas.openxmlformats.org/spreadsheetml/2006/main", Local: "cellStyleXfs"},
				xml.Name{Space: "http://purl.oclc.org/ooxml/spreadsheetml/main", Local: "cellStyleXfs"}:
				m.CellStyleXfs = NewCT_CellStyleXfs()
				if err := d.DecodeElement(m.CellStyleXfs, &el); err != nil {
					return err
				}
			case xml.Name{Space: "http://schemas.openxmlformats.org/spreadsheetml/2006/main", Local: "cellXfs"},
				xml.Name{Space: "http://purl.oclc.org/ooxml/spreadsheetml/main", Local: "cellXfs"}:
				m.CellXfs = NewCT_CellXfs()
				if err := d.DecodeElement(m.CellXfs, &el); err != nil {
					return err
				}
			case xml.Name{Space: "http://schemas.openxmlformats.org/spreadsheetml/2006/main", Local: "cellStyles"},
				xml.Name{Space: "http://purl.oclc.org/ooxml/spreadsheetml/main", Local: "cellStyles"}:
				m.CellStyles = NewCT_CellStyles()
				if err := d.DecodeElement(m.CellStyles, &el); err != nil {
					return err
				}
			case xml.Name{Space: "http://schemas.openxmlformats.org/spreadsheetml/2006/main", Local: "dxfs"},
				xml.Name{Space: "http://purl.oclc.org/ooxml/spreadsheetml/main", Local: "dxfs"}:
				m.Dxfs = NewCT_Dxfs()
				if err := d.DecodeElement(m.Dxfs, &el); err != nil {
					return err
				}
			case xml.Name{Space: "http://schemas.openxmlformats.org/spreadsheetml/2006/main", Local: "tableStyles"},
				xml.Name{Space: "http://purl.oclc.org/ooxml/spreadsheetml/main", Local: "tableStyles"}:
				m.TableStyles = NewCT_TableStyles()
				if err := d.DecodeElement(m.TableStyles, &el); err != nil {
					return err
				}
			case xml.Name{Space: "http://schemas.openxmlformats.org/spreadsheetml/2006/main", Local: "colors"},
				xml.Name{Space: "http://purl.oclc.org/ooxml/spreadsheetml/main", Local: "colors"}:
				m.Colors = NewCT_Colors()
				if err := d.DecodeElement(m.Colors, &el); err != nil {
					return err
				}
			case xml.Name{Space: "http://schemas.openxmlformats.org/spreadsheetml/2006/main", Local: "extLst"},
				xml.Name{Space: "http://purl.oclc.org/ooxml/spreadsheetml/main", Local: "extLst"}:
				m.ExtLst = NewCT_ExtensionList()
				if err := d.DecodeElement(m.ExtLst, &el); err != nil {
					return err
				}
			default:
				office.Log("skipping unsupported element on CT_Stylesheet %v", el.Name)
				if err := d.Skip(); err != nil {
					return err
				}
			}
		case xml.EndElement:
			break lCT_Stylesheet
		case xml.CharData:
		}
	}
	return nil
}

// Validate validates the CT_Stylesheet and its children
func (m *CT_Stylesheet) Validate() error {
	return m.ValidateWithPath("CT_Stylesheet")
}

// ValidateWithPath validates the CT_Stylesheet and its children, prefixing error messages with path
func (m *CT_Stylesheet) ValidateWithPath(path string) error {
	if m.NumFmts != nil {
		if err := m.NumFmts.ValidateWithPath(path + "/NumFmts"); err != nil {
			return err
		}
	}
	if m.Fonts != nil {
		if err := m.Fonts.ValidateWithPath(path + "/Fonts"); err != nil {
			return err
		}
	}
	if m.Fills != nil {
		if err := m.Fills.ValidateWithPath(path + "/Fills"); err != nil {
			return err
		}
	}
	if m.Borders != nil {
		if err := m.Borders.ValidateWithPath(path + "/Borders"); err != nil {
			return err
		}
	}
	if m.CellStyleXfs != nil {
		if err := m.CellStyleXfs.ValidateWithPath(path + "/CellStyleXfs"); err != nil {
			return err
		}
	}
	if m.CellXfs != nil {
		if err := m.CellXfs.ValidateWithPath(path + "/CellXfs"); err != nil {
			return err
		}
	}
	if m.CellStyles != nil {
		if err := m.CellStyles.ValidateWithPath(path + "/CellStyles"); err != nil {
			return err
		}
	}
	if m.Dxfs != nil {
		if err := m.Dxfs.ValidateWithPath(path + "/Dxfs"); err != nil {
			return err
		}
	}
	if m.TableStyles != nil {
		if err := m.TableStyles.ValidateWithPath(path + "/TableStyles"); err != nil {
			return err
		}
	}
	if m.Colors != nil {
		if err := m.Colors.ValidateWithPath(path + "/Colors"); err != nil {
			return err
		}
	}
	if m.ExtLst != nil {
		if err := m.ExtLst.ValidateWithPath(path + "/ExtLst"); err != nil {
			return err
		}
	}
	return nil
}
