package import_resolve

import (
  "path/filepath"

  "github.com/marzeq/quokka/parser"
  "github.com/marzeq/quokka/shared"
  "github.com/marzeq/quokka/tokeniser"
)

type (
  Node = parser.Node
)

func ProcessImports(root *Node, loaded map[string]*Node, recStack map[string]bool) (*Node, error) {
  filePath := root.Loc.FilePath

  if recStack[filePath] {
    return nil, shared.NewError(root.Loc, "import cycle detected for file '%s'", filePath)
  }

  if merged, ok := loaded[filePath]; ok {
    return merged, nil
  }

  recStack[filePath] = true

  merged := &Node{
    Type:     root.Type,
    Loc:      root.Loc,
    Children: []*Node{},
  }

  for _, node := range root.Children {
    if node.Type != parser.NODE_TYPE_IMPORT {
      continue
    }

    importPath := node.Right.Value.(string)

    resolvedPath := filepath.Join(filepath.Dir(filePath), importPath)

    t, err := tokeniser.NewTokeniserFromFile(resolvedPath)
    if err != nil {
      switch err.(type) {
      case shared.Error:
        return nil, err
      default:
        return nil, shared.NewError(node.Loc, "import failed: %v", err)
      }
    }
    toks, err := t.Tokenise()
    if err != nil {
      return nil, err
    }
    p := parser.NewParser(toks)
    ast, err := p.Parse()
    if err != nil {
      return nil, err
    }

    importedMerged, err := ProcessImports(ast, loaded, recStack)
    if err != nil {
      return nil, err
    }

    merged.Children = append(merged.Children, importedMerged.Children...)
  }

  for _, node := range root.Children {
    if node.Type != parser.NODE_TYPE_IMPORT {
      merged.Children = append(merged.Children, node)
    }
  }

  loaded[filePath] = merged
  delete(recStack, filePath)
  return merged, nil
}