package d2ir

import (
	
	
	
	
	

	
	
)

func ( *compiler) ( *d2ast.Import) (string, bool) {
	 := .PathWithPre()
	if  == "" && .Range != (d2ast.Range{}) {
		.errorf(, "imports must specify a path to import")
		return "", false
	}
	if len(.importStack) > 0 {
		if path.Ext() != ".d2" {
			 += ".d2"
		}

		if !filepath.IsAbs() {
			 = path.Join(path.Dir(.importStack[len(.importStack)-1]), )
		}
	}

	for ,  := range .importStack {
		if  ==  {
			.errorf(, "detected cyclic import chain: %s", formatCyclicChain(.importStack[:]))
			return "", false
		}
	}

	.importStack = append(.importStack, )
	return , true
}

func ( *compiler) () {
	.importStack = .importStack[:len(.importStack)-1]
}

func formatCyclicChain( []string) string {
	var  strings.Builder
	for ,  := range  {
		.WriteString()
		.WriteString(" -> ")
	}
	.WriteString([0])
	return .String()
}

// Returns either *Map or *Field.
func ( *compiler) ( *d2ast.Import) (Node, bool) {
	,  := .__import()
	if ! {
		return nil, false
	}
	nilScopeMap()
	if len(.IDA()) > 0 {
		 := .GetField(.IDA()...)
		if  == nil {
			.errorf(, "import key %q doesn't exist inside import", .IDA())
			return nil, false
		}
		return , true
	}
	return , true
}

func ( *compiler) ( *d2ast.Import) (*Map, bool) {
	,  := .pushImportStack()
	if ! {
		return nil, false
	}
	defer .popImportStack()

	// Only get immediate imports.
	if len(.importStack) == 2 {
		if ,  := .seenImports[]; ! {
			.imports = append(.imports, .PathWithPre())
		}
	}

	var  fs.File
	var  error
	if .fs == nil {
		,  = os.Open()
	} else {
		,  = .fs.Open()
	}
	if  != nil {
		.errorf(, "failed to import %q: %v", , )
		return nil, false
	}
	defer .Close()

	,  := d2parser.Parse(, , &d2parser.ParseOptions{
		UTF16Pos:   .utf16Pos,
		ParseError: .err,
	})
	if  != nil {
		return nil, false
	}

	 := &Map{}
	.initRoot()
	.parent.(*Field).References[0].Context_.Scope = 

	.compileMap(, , )

	.seenImports[] = struct{}{}

	return , true
}

func nilScopeMap( Node) {
	switch n := .(type) {
	case *Map:
		for ,  := range .Fields {
			()
		}
		for ,  := range .Edges {
			()
		}
	case *Edge:
		for ,  := range .References {
			.Context_.ScopeMap = nil
		}
		if .Map() != nil {
			(.Map())
		}
	case *Field:
		for ,  := range .References {
			.Context_.ScopeMap = nil
		}
		if .Map() != nil {
			(.Map())
		}
	}
}