package d2exporter

import (
	
	
	
	

	

	
	
	
	
	
	
	
)

func ( context.Context,  *d2graph.Graph,  *d2fonts.FontFamily) (*d2target.Diagram, error) {
	 := d2target.NewDiagram()
	applyStyles(&.Root, .Root)
	if .Root.Label.MapKey == nil {
		.Root.Label = .Name
	} else {
		.Root.Label = .Root.Label.Value
	}
	.Name = .Name
	.IsFolderOnly = .IsFolderOnly
	if  == nil {
		 = go2.Pointer(d2fonts.SourceSansPro)
	}
	if .Theme != nil && .Theme.SpecialRules.Mono {
		 = go2.Pointer(d2fonts.SourceCodePro)
	}
	.FontFamily = 

	.Shapes = make([]d2target.Shape, len(.Objects))
	for  := range .Objects {
		.Shapes[] = toShape(.Objects[], )
	}

	.Connections = make([]d2target.Connection, len(.Edges))
	for  := range .Edges {
		.Connections[] = toConnection(.Edges[], .Theme)
	}

	return , nil
}

func applyTheme( *d2target.Shape,  *d2graph.Object,  *d2themes.Theme) {
	.Stroke = .GetStroke(.StrokeDash)
	.Fill = .GetFill()
	if .Shape.Value == d2target.ShapeText {
		.Color = color.N1
	}
	if .Shape.Value == d2target.ShapeSQLTable || .Shape.Value == d2target.ShapeClass {
		.PrimaryAccentColor = color.B2
		.SecondaryAccentColor = color.AA2
		.NeutralAccentColor = color.N2
	}

	// Theme options that change more than color
	if  != nil {
		if .SpecialRules.OuterContainerDoubleBorder {
			if .Level() == 1 && len(.ChildrenArray) > 0 {
				.DoubleBorder = true
			}
		}
		if .SpecialRules.ContainerDots {
			if len(.ChildrenArray) > 0 {
				.FillPattern = "dots"
			}
		} else if .SpecialRules.AllPaper {
			.FillPattern = "paper"
		}
		if .SpecialRules.Mono {
			.FontFamily = "mono"
		}
	}
}

func applyStyles( *d2target.Shape,  *d2graph.Object) {
	if .Style.Opacity != nil {
		.Opacity, _ = strconv.ParseFloat(.Style.Opacity.Value, 64)
	}
	if .Style.StrokeDash != nil {
		.StrokeDash, _ = strconv.ParseFloat(.Style.StrokeDash.Value, 64)
	}
	if .Style.Fill != nil {
		.Fill = .Style.Fill.Value
	} else if .Shape.Value == d2target.ShapeText {
		.Fill = "transparent"
	}
	if .Style.FillPattern != nil {
		.FillPattern = .Style.FillPattern.Value
	}
	if .Style.Stroke != nil {
		.Stroke = .Style.Stroke.Value
	}
	if .Style.StrokeWidth != nil {
		.StrokeWidth, _ = strconv.Atoi(.Style.StrokeWidth.Value)
	}
	if .Style.Shadow != nil {
		.Shadow, _ = strconv.ParseBool(.Style.Shadow.Value)
	}
	if .Style.ThreeDee != nil {
		.ThreeDee, _ = strconv.ParseBool(.Style.ThreeDee.Value)
	}
	if .Style.Multiple != nil {
		.Multiple, _ = strconv.ParseBool(.Style.Multiple.Value)
	}
	if .Style.BorderRadius != nil {
		.BorderRadius, _ = strconv.Atoi(.Style.BorderRadius.Value)
	}

	if .Style.FontColor != nil {
		.Color = .Style.FontColor.Value
	}
	if .Style.Italic != nil {
		.Italic, _ = strconv.ParseBool(.Style.Italic.Value)
	}
	if .Style.Bold != nil {
		.Bold, _ = strconv.ParseBool(.Style.Bold.Value)
	}
	if .Style.Underline != nil {
		.Underline, _ = strconv.ParseBool(.Style.Underline.Value)
	}
	if .Style.Font != nil {
		.FontFamily = .Style.Font.Value
	}
	if .Style.DoubleBorder != nil {
		.DoubleBorder, _ = strconv.ParseBool(.Style.DoubleBorder.Value)
	}
}

func toShape( *d2graph.Object,  *d2graph.Graph) d2target.Shape {
	 := d2target.BaseShape()
	.SetType(.Shape.Value)
	.ID = .AbsID()
	.Classes = .Classes
	.ZIndex = .ZIndex
	.Level = int(.Level())
	.Pos = d2target.NewPoint(int(.TopLeft.X), int(.TopLeft.Y))
	.Width = int(.Width)
	.Height = int(.Height)

	 := .Text()
	.Bold = .IsBold
	.Italic = .IsItalic
	.FontSize = .FontSize

	if .IsSequenceDiagram() {
		.StrokeWidth = 0
	}

	if .IsSequenceDiagramGroup() {
		.StrokeWidth = 0
		.Blend = true
	}

	applyStyles(, )
	applyTheme(, , .Theme)
	.Color = .GetColor(.Italic)
	applyStyles(, )

	switch .Shape.Value {
	case d2target.ShapeCode, d2target.ShapeText:
		.Language = .Language
		.Label = .Label.Value
	case d2target.ShapeClass:
		.Class = *.Class
		// The label is the header for classes and tables, which is set in client to be 4 px larger than the object's set font size
		.FontSize -= d2target.HeaderFontAdd
	case d2target.ShapeSQLTable:
		.SQLTable = *.SQLTable
		.FontSize -= d2target.HeaderFontAdd
	case d2target.ShapeCloud:
		if .ContentAspectRatio != nil {
			.ContentAspectRatio = go2.Pointer(*.ContentAspectRatio)
		}
	}
	.Label = .Text
	.LabelWidth = .Dimensions.Width

	.LabelHeight = .Dimensions.Height
	if .LabelPosition != nil {
		.LabelPosition = *.LabelPosition
		if .IsSequenceDiagramGroup() {
			.LabelFill = .Fill
		}
	}

	if .Tooltip != nil {
		.Tooltip = .Tooltip.Value
	}
	if .Style.Animated != nil {
		.Animated, _ = strconv.ParseBool(.Style.Animated.Value)
	}
	if .Link != nil {
		.Link = .Link.Value
		.PrettyLink = toPrettyLink(, .Link.Value)
	}
	.Icon = .Icon
	if .IconPosition != nil {
		.IconPosition = *.IconPosition
	}

	return *
}

func toPrettyLink( *d2graph.Graph,  string) string {
	,  := url.ParseRequestURI()
	if  == nil && .Host != "" && len(.RawPath) > 30 {
		return .Scheme + "://" + .Host + .RawPath[:10] + "..." + .RawPath[len(.RawPath)-10:]
	} else if  != nil {
		,  := d2parser.ParseKey()
		if  != nil {
			return 
		}
		 := 
		for .Parent != nil {
			 = .Parent
		}
		var  []string
	:
		for  := 0;  < len(.Path); ++ {
			 := .Path[].Unbox().ScalarString()
			if  > 0 {
				switch  {
				case "layers", "scenarios", "steps":
					continue 
				}
				 = .GetBoard()
				if  == nil {
					return 
				}
			}
			if .Root.Label.MapKey != nil {
				 = append(, .Root.Label.Value)
			} else {
				 = append(, .Name)
			}
		}
		for ,  := range  {
			// If any part of it is blank, "x > > y" looks stupid, so just use the last
			if  == "" {
				return [len()-1]
			}
		}
		return strings.Join(, " > ")
	}
	return 
}

func toConnection( *d2graph.Edge,  *d2themes.Theme) d2target.Connection {
	 := d2target.BaseConnection()
	.ID = .AbsID()
	.Classes = .Classes
	.ZIndex = .ZIndex
	 := .Text()

	if .SrcArrow {
		.SrcArrow = d2target.DefaultArrowhead
		if .SrcArrowhead != nil {
			.SrcArrow = .SrcArrowhead.ToArrowhead()
		}
	}
	if .SrcArrowhead != nil {
		if .SrcArrowhead.Label.Value != "" {
			.SrcLabel = &d2target.Text{
				Label:       .SrcArrowhead.Label.Value,
				LabelWidth:  .SrcArrowhead.LabelDimensions.Width,
				LabelHeight: .SrcArrowhead.LabelDimensions.Height,
			}
			if .SrcArrowhead.Style.FontColor != nil {
				.SrcLabel.Color = .SrcArrowhead.Style.FontColor.Value
			}
		}
	}
	if .DstArrow {
		.DstArrow = d2target.DefaultArrowhead
		if .DstArrowhead != nil {
			.DstArrow = .DstArrowhead.ToArrowhead()
		}
	}
	if .DstArrowhead != nil {
		if .DstArrowhead.Label.Value != "" {
			.DstLabel = &d2target.Text{
				Label:       .DstArrowhead.Label.Value,
				LabelWidth:  .DstArrowhead.LabelDimensions.Width,
				LabelHeight: .DstArrowhead.LabelDimensions.Height,
			}
			if .DstArrowhead.Style.FontColor != nil {
				.DstLabel.Color = .DstArrowhead.Style.FontColor.Value
			}
		}
	}
	if  != nil && .SpecialRules.NoCornerRadius {
		.BorderRadius = 0
	}
	if .Style.BorderRadius != nil {
		.BorderRadius, _ = strconv.ParseFloat(.Style.BorderRadius.Value, 64)
	}

	if .Style.Opacity != nil {
		.Opacity, _ = strconv.ParseFloat(.Style.Opacity.Value, 64)
	}

	if .Style.StrokeDash != nil {
		.StrokeDash, _ = strconv.ParseFloat(.Style.StrokeDash.Value, 64)
	}
	.Stroke = .GetStroke(.StrokeDash)
	if .Style.Stroke != nil {
		.Stroke = .Style.Stroke.Value
	}

	if .Style.StrokeWidth != nil {
		.StrokeWidth, _ = strconv.Atoi(.Style.StrokeWidth.Value)
	}

	if .Style.Fill != nil {
		.Fill = .Style.Fill.Value
	}

	.FontSize = .FontSize
	if .Style.FontSize != nil {
		.FontSize, _ = strconv.Atoi(.Style.FontSize.Value)
	}

	if .Style.Animated != nil {
		.Animated, _ = strconv.ParseBool(.Style.Animated.Value)
	}

	if .Tooltip != nil {
		.Tooltip = .Tooltip.Value
	}
	.Icon = .Icon

	if .Style.Italic != nil {
		.Italic, _ = strconv.ParseBool(.Style.Italic.Value)
	}

	.Color = .GetColor(.Italic)
	if .Style.FontColor != nil {
		.Color = .Style.FontColor.Value
	}
	if .Style.Bold != nil {
		.Bold, _ = strconv.ParseBool(.Style.Bold.Value)
	}
	if .Style.Underline != nil {
		.Underline, _ = strconv.ParseBool(.Style.Underline.Value)
	}
	if  != nil && .SpecialRules.Mono {
		.FontFamily = "mono"
	}
	if .Style.Font != nil {
		.FontFamily = .Style.Font.Value
	}
	if .Link != nil {
		.Link = .Link.Value
	}
	.Label = .Text
	.LabelWidth = .Dimensions.Width
	.LabelHeight = .Dimensions.Height

	if .LabelPosition != nil {
		.LabelPosition = *.LabelPosition
	}
	if .LabelPercentage != nil {
		.LabelPercentage = float64(float32(*.LabelPercentage))
	}
	.Route = make([]*geo.Point, 0, len(.Route))
	for  := range .Route {
		 := .Route[].Copy()
		.TruncateDecimals()
		.TruncateFloat32()
		.Route = append(.Route, )
	}

	.IsCurve = .IsCurve

	.Src = .Src.AbsID()
	.Dst = .Dst.AbsID()

	return *
}