// Copyright 2019-2020 Celer Network
//
// Generate a Go array of SQL commands from a schema file.
// This allows the client SDK to contain the schema commands
// to create a SQLite database.

package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"strings"
)

const (
	sqliteStart = "START OF PORTABLE SCHEMA"
)

var (
	pretend = flag.Bool("n", false, "don't write files, only to stdout")
)

func sql2go(fname string) error {
	in, err := os.Open(fname)
	if err != nil {
		return err
	}
	defer in.Close()

	out := os.Stdout
	if !*pretend {
		fn := fmt.Sprintf("%s.go", fname)
		out, err = os.Create(fn)
		if err != nil {
			return err
		}
		defer out.Close()
	}

	scanner := bufio.NewScanner(in)
	start := false
	var buf, sqlCmds []string
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if len(line) == 0 {
			continue
		}
		if !start {
			if strings.Contains(line, sqliteStart) {
				start = true
			}
			continue
		}
		if pos := strings.Index(line, "--"); pos >= 0 {
			line = line[:pos] // strip trailing comment
			if len(line) == 0 {
				continue
			}
		}

		buf = append(buf, line)
		if strings.HasSuffix(line, ");") {
			cmd := strings.Join(buf, " ")
			sqlCmds = append(sqlCmds, cmd)
			buf = nil
		}
	}

	if err = scanner.Err(); err != nil {
		return err
	}

	fmt.Fprintf(out, "// Code generated by sql2go. DO NOT EDIT.\n")
	fmt.Fprintf(out, "// source: %s\n\n", fname)
	fmt.Fprintf(out, "package storage\n\n")
	fmt.Fprintf(out, "var sqlSchemaCmds = [...]string{\n")
	for _, cmd := range sqlCmds {
		fmt.Fprintf(out, "\t\"%s\",\n", cmd)
	}
	fmt.Fprintf(out, "}\n")
	return nil
}

func main() {
	flag.Parse()
	args := flag.Args()
	nargs := len(args)
	if len(args) == 0 {
		fmt.Fprintf(os.Stderr, "must provide a list of files to convert\n")
		os.Exit(1)
	}

	ex := 0
	for _, f := range args {
		if nargs > 1 {
			fmt.Printf("%s:\n", f)
		}

		if err := sql2go(f); err != nil {
			fmt.Fprintln(os.Stderr, err)
			ex = 1
		}

		if *pretend && nargs > 1 {
			fmt.Printf("\n")
		}
	}

	os.Exit(ex)
}
