package d2themes

import (
	
	
	

	
	
)

// ThemableElement is a helper class for creating new XML elements.
// This should be preferred over formatting and must be used
// whenever Fill, Stroke, BackgroundColor or Color contains a color from a theme.
// i.e. N[1-7] | B[1-6] | AA[245] | AB[45]
type ThemableElement struct {
	tag string

	X      float64
	X1     float64
	X2     float64
	Y      float64
	Y1     float64
	Y2     float64
	Width  float64
	Height float64
	R      float64
	Rx     float64
	Ry     float64
	Cx     float64
	Cy     float64

	D         string
	Points    string
	Transform string
	Href      string
	Xmlns     string

	Fill            string
	Stroke          string
	StrokeDashArray string
	BackgroundColor string
	Color           string

	ClassName string
	Style     string
	// Mask is retained for source compatibility and must be a local IRI in the
	// form url(#id). Deprecated: use SetMaskID.
	Mask string
	// ClipPath is retained for source compatibility and must contain a local
	// identifier. Deprecated: use SetClipPathID.
	ClipPath string
	// Attributes is retained for source compatibility. Values are parsed and
	// re-serialized through lib/svg; malformed or event attributes panic.
	// Deprecated: use AddAttributes.
	Attributes string

	// Content is retained as a trusted-markup compatibility escape hatch.
	// Deprecated: use SetText or SetInnerSVG.
	Content string

	FillPattern string

	inlineTheme     *Theme
	extraAttributes []svg.Attribute
	inner           *svg.Fragment
	mask            string
	clipPath        string
}

func ( string,  *Theme) *ThemableElement {
	 := ""
	if  == "div" {
		 = "http://www.w3.org/1999/xhtml"
	}

	return &ThemableElement{
		tag:             ,
		X:               math.MaxFloat64,
		X1:              math.MaxFloat64,
		X2:              math.MaxFloat64,
		Y:               math.MaxFloat64,
		Y1:              math.MaxFloat64,
		Y2:              math.MaxFloat64,
		Width:           math.MaxFloat64,
		Height:          math.MaxFloat64,
		R:               math.MaxFloat64,
		Rx:              math.MaxFloat64,
		Ry:              math.MaxFloat64,
		Cx:              math.MaxFloat64,
		Cy:              math.MaxFloat64,
		Xmlns:           ,
		Fill:            color.Empty,
		Stroke:          color.Empty,
		StrokeDashArray: color.Empty,
		BackgroundColor: color.Empty,
		inlineTheme:     ,
	}
}

func ( *ThemableElement) () *ThemableElement {
	 := *
	.extraAttributes = append([]svg.Attribute(nil), .extraAttributes...)
	return &
}

func ( *ThemableElement) ( ...svg.Attribute) {
	.extraAttributes = append(.extraAttributes, ...)
}

func ( *ThemableElement) ( string) {
	 := svg.Text()
	.inner = &
}

func ( *ThemableElement) ( svg.Fragment) {
	.inner = &
}

func ( *ThemableElement) (,  float64) {
	.Transform = fmt.Sprintf("translate(%s %s)", svg.FormatFloat(), svg.FormatFloat())
}

func ( *ThemableElement) ( svg.ID) {
	.mask = svg.LocalIRI()
}

// SetMaskUrl is retained for source compatibility.
// Deprecated: use SetMaskID.
func ( *ThemableElement) ( string) {
	.SetMaskID(svg.LiteralID())
}

func ( *ThemableElement) ( svg.ID) {
	.clipPath = .String()
}

func ( *ThemableElement) () string {
	 := make([]svg.Attribute, 0, 24+len(.extraAttributes))
	// href has to be at the top for the img bundler to detect <image> tags correctly
	if len(.Href) > 0 {
		 = append(, svg.Attr("href", .Href))
	}
	if .X != math.MaxFloat64 {
		 = append(, svg.FloatAttr("x", .X))
	}
	if .X1 != math.MaxFloat64 {
		 = append(, svg.FloatAttr("x1", .X1))
	}
	if .X2 != math.MaxFloat64 {
		 = append(, svg.FloatAttr("x2", .X2))
	}
	if .Y != math.MaxFloat64 {
		 = append(, svg.FloatAttr("y", .Y))
	}
	if .Y1 != math.MaxFloat64 {
		 = append(, svg.FloatAttr("y1", .Y1))
	}
	if .Y2 != math.MaxFloat64 {
		 = append(, svg.FloatAttr("y2", .Y2))
	}
	if .Width != math.MaxFloat64 {
		 = append(, svg.FloatAttr("width", .Width))
	}
	if .Height != math.MaxFloat64 {
		 = append(, svg.FloatAttr("height", .Height))
	}
	if .R != math.MaxFloat64 {
		 = append(, svg.FloatAttr("r", .R))
	}
	if .Rx != math.MaxFloat64 {
		 = append(, svg.FloatAttr("rx", calculateAxisRadius(.Rx, .Width, .Height)))
	}
	if .Ry != math.MaxFloat64 {
		 = append(, svg.FloatAttr("ry", calculateAxisRadius(.Ry, .Width, .Height)))
	}
	if .Cx != math.MaxFloat64 {
		 = append(, svg.FloatAttr("cx", .Cx))
	}
	if .Cy != math.MaxFloat64 {
		 = append(, svg.FloatAttr("cy", .Cy))
	}
	if .StrokeDashArray != "" {
		 = append(, svg.Attr("stroke-dasharray", .StrokeDashArray))
	}

	if len(.D) > 0 {
		 = append(, svg.Attr("d", .D))
	}
	 := .mask
	if  == "" && .Mask != "" {
		,  := svg.ParseLocalIRI(.Mask)
		if  != nil {
			panic()
		}
		 = svg.LocalIRI()
	}
	if len() > 0 {
		 = append(, svg.Attr("mask", ))
	}
	if len(.Points) > 0 {
		 = append(, svg.Attr("points", .Points))
	}
	if len(.Transform) > 0 {
		 = append(, svg.Attr("transform", .Transform))
	}
	if len(.Xmlns) > 0 {
		 = append(, svg.Attr("xmlns", .Xmlns))
	}

	 := .ClassName
	 := .Style

	// Add class {property}-{theme color} if the color is from a theme, set the property otherwise
	if color.IsThemeColor(.Stroke) {
		 += fmt.Sprintf(" stroke-%s", .Stroke)
		if .inlineTheme != nil {
			 = append(, svg.Attr("stroke", ResolveThemeColor(*.inlineTheme, .Stroke)))
		}
	} else if len(.Stroke) > 0 {
		if color.IsGradient(.Stroke) {
			.Stroke = fmt.Sprintf("url('#%s')", color.UniqueGradientID(.Stroke))
		}
		 = append(, svg.Attr("stroke", .Stroke))
	}
	if color.IsThemeColor(.Fill) {
		 += fmt.Sprintf(" fill-%s", .Fill)
		if .inlineTheme != nil {
			 = append(, svg.Attr("fill", ResolveThemeColor(*.inlineTheme, .Fill)))
		}
	} else if len(.Fill) > 0 {
		if color.IsGradient(.Fill) {
			.Fill = fmt.Sprintf("url('#%s')", color.UniqueGradientID(.Fill))
		}
		 = append(, svg.Attr("fill", .Fill))
	}
	if color.IsThemeColor(.BackgroundColor) {
		 += fmt.Sprintf(" background-color-%s", .BackgroundColor)
		if .inlineTheme != nil {
			 = append(, svg.Attr("background-color", ResolveThemeColor(*.inlineTheme, .BackgroundColor)))
		}
	} else if len(.BackgroundColor) > 0 {
		 = append(, svg.Attr("background-color", .BackgroundColor))
	}
	if color.IsThemeColor(.Color) {
		 += fmt.Sprintf(" color-%s", .Color)
		if .inlineTheme != nil {
			 = append(, svg.Attr("color", ResolveThemeColor(*.inlineTheme, .Color)))
		}
	} else if len(.Color) > 0 {
		 = append(, svg.Attr("color", .Color))
	}

	if len() > 0 {
		 = append(, svg.Attr("class", ))
	}
	if len() > 0 {
		 = append(, svg.Attr("style", ))
	}
	 = append(, .extraAttributes...)

	if .Attributes != "" {
		,  := svg.ParseAttributes(.Attributes)
		if  != nil {
			panic()
		}
		 = append(, ...)
	}
	 := .clipPath
	if  == "" && .ClipPath != "" {
		 = svg.LiteralID(.ClipPath).String()
	}
	if len() > 0 {
		 = append(, svg.Attr("clip-path", svg.LocalIRI(svg.LiteralID())))
	}

	 := svg.OpenElement(.tag, ...)
	 := .inner
	if  == nil && .Content != "" {
		 := svg.TrustedFragment(.Content)
		 = &
	}
	if  != nil && len(.String()) > 0 {
		return strings.TrimSuffix(, ">") + ">" + .String() + svg.CloseElement(.tag)
	}

	 = strings.TrimSuffix(, ">") + " />"
	 := strings.ToLower(.FillPattern)
	if  != "" &&  != "none" {
		 := .Copy()
		.Fill = ""
		.Stroke = ""
		.BackgroundColor = ""
		.Color = ""
		.ClassName = fmt.Sprintf("%s-overlay", )
		.FillPattern = ""
		 += .()
	}
	return 
}

func calculateAxisRadius(, ,  float64) float64 {
	 := math.Min(, )
	 :=  / 2.0
	return math.Min(, )
}