package main

import (
	"encoding/json"
	"flow"
	"flow/registry"
	"flowserver"
	"log"

	"github.com/gohxs/prettylog"
)

const jsonRaw = `
{
 "nodes": [
  {
   "id": "38d76987-290f-ea1d-0ba0-3c63c1bde6a0",
   "label": "MatMul",
   "src": "StrCat",
   "x": 447,
   "y": 290.34375
  },
  {
   "id": "378e389b-27d3-8b66-90fa-664bcab18a38",
   "label": "Variable",
   "src": "Variable",
   "x": 229,
   "y": 383.34375
  },
  {
   "id": "3e589bf7-f415-7a31-94e4-7ec8fa28b0c1",
   "label": "Input",
   "src": "Input",
   "x": 250,
   "y": 165.34375
  },
  {
   "id": "97d5a94f-0e43-df2d-e97d-f347dd186682",
   "label": "Activator",
   "src": "StrReverse",
   "x": 637,
   "y": 332.34375
  }
 ],
 "links": [
  {
   "from": "3e589bf7-f415-7a31-94e4-7ec8fa28b0c1",
   "in": 0,
   "to": "38d76987-290f-ea1d-0ba0-3c63c1bde6a0"
  },
  {
   "from": "378e389b-27d3-8b66-90fa-664bcab18a38",
   "in": 1,
   "to": "38d76987-290f-ea1d-0ba0-3c63c1bde6a0"
  },
  {
   "from": "38d76987-290f-ea1d-0ba0-3c63c1bde6a0",
   "in": 0,
   "to": "97d5a94f-0e43-df2d-e97d-f347dd186682"
  }
 ]
}`

func main() {
	prettylog.Global()
	doc := flowserver.FlowDocument{
		Nodes: []flowserver.Node{},
		Links: []flowserver.Link{},
	}
	json.Unmarshal([]byte(jsonRaw), &doc)
	// Handling flow
	//
	reg := registry.New()
	reg.Register("StrCat", StrCat)
	reg.Register("StrReverse", StrReverse)

	f := flow.New()
	f.SetRegistry(reg)

	nodeMap := map[string]flowserver.Node{}
	for _, n := range doc.Nodes {
		nodeMap[n.ID] = n
	}
	inputMap := map[string]flow.Operation{}

	ninput := 0
	for _, n := range doc.Nodes {
		// Find link refered as To
		param := make([]interface{}, 10) // 10 is temporary to test out operations
		lastParamID := -1
		for _, l := range doc.Links {
			if l.To != n.ID {
				continue
			}
			if l.In > lastParamID {
				lastParamID = l.In
			}
			// Define operators here
			from := nodeMap[l.From]
			switch from.Src {
			case "Input":
				inOp, ok := inputMap[n.ID]
				if !ok {
					inOp = f.In(ninput)
					inputMap[n.ID] = inOp
					ninput++
				}
				param[l.In] = inOp // By id perhaps
			case "Variable":
				param[l.In] = f.Var(from.ID, "Temporary")
			default:
				param[l.In] = f.Res(from.ID)
			}
		}
		param = param[:lastParamID+1]
		if n.Src == "Input" || n.Src == "Variable" {
			continue
		}
		f.DefOp(n.ID, n.Src, param...)
	}

	log.Println("Flow:\n", f)
	f.Analyse(nil, "my string")

}

func StrCat(a1 string, a2 string) string {
	return a1 + a2
}
func StrReverse(s string) string {
	n := len(s)
	runes := make([]rune, n)
	for _, r := range s {
		n--
		runes[n] = r
	}
	return string(runes[n:])
}
