package main

import (
	"flow"
	"flow/flowserver"
	"flow/registry"
	"fmt"
	"io"
	"log"
	"math"
	"strings"
	"time"

	"github.com/gohxs/prettylog"
)

func main() {
	prettylog.Global()
	log.Println("Running version:", flowserver.Version)

	registry.MakeBatch(
		registry.Add(strings.Split).DescInputs("string", "separator"),
		registry.Add(strings.Join).DescInputs("", "sep"),
		registry.Add(strings.Compare, strings.Contains),
		registry.Register("Cat", func(a, b string) string { return a + " " + b }),
		registry.Register("ToString", func(a interface{}) string { return fmt.Sprint(a) }),
	).Tags("string").Extra("style", registry.M{"color": "#839"})

	// Math functions
	registry.Add(
		math.Abs, math.Cos, math.Sin, math.Exp, math.Exp2, math.Tanh, math.Max, math.Min,
	).Tags("math").Extra("style", registry.M{"color": "#386"})

	// Test functions
	registry.Add(customNew, customEmpty, customSetName, customSetURL).
		Tags("testing")

	registry.Add(testErrorPanic, testErrorDelayed).
		Tags("testing-errors")

	registry.Batch{
		registry.Register("wait", wait),
	}.Tags("testing-time").Extra("style", map[string]string{"color": "#8a5"})

	addr := ":2015"
	log.Println("Starting server  at:", ":2015")

	f := flowserver.FlowServer{}
	f.ListenAndServe(addr)
}

func wait(data flow.Data, n int) flow.Data {
	time.Sleep(time.Duration(n) * time.Second) // Simulate
	return data
}

func stream(w io.Writer, val interface{}) interface{} {
	fmt.Fprint(w, val)
	return val
}

////////////////////
// Testing custom struct operations
/////

// CustomStruct testing custom struct passing
type CustomStruct struct {
	Name string
	URL  string
}

func customNew(name string, url string) CustomStruct {
	return CustomStruct{name, url}
}
func customEmpty() CustomStruct {
	return CustomStruct{}
}
func customSetName(a CustomStruct, name string) CustomStruct {
	a.Name = name
	return a
}
func customSetURL(a CustomStruct, url string) CustomStruct {
	a.URL = url
	return a
}

////////////////////////
// testOps
////////////////
func testErrorPanic(n int) flow.Data {
	dur := time.Duration(n)
	time.Sleep(dur * time.Second)
	panic("I panicked")
}

func testErrorDelayed(n int) (flow.Data, error) {
	dur := time.Duration(n)
	time.Sleep(dur * time.Second)
	return nil, fmt.Errorf("I got an error %v", dur)
}
