package main

import (
	"flag"
	"fmt"
	"os"
	"strconv"

	"github.com/iancoleman/orderedmap"
)

var testDefinitions *TestDefinitions
var captureValues *CaptureValues

func main() {
	var s []byte
	var err error
	//var ok bool

	// Prepare struct to store settings common to all tests
	testDefinitions = new(TestDefinitions)
	captureValues = new(CaptureValues)
	captureValues.Data = make(map[string]string)

	// Command line arguments
	var inputJson string

	// Process command line arguments
	flag.StringVar(&inputJson, "input", "./tests.json", "Full path to input json test definition file")
	flag.Parse()

	// Read the json input file
	if fileExists(inputJson) {
		s, err = os.ReadFile(inputJson)
		if err != nil {
			panic(err)
		}
	} else {
		fmt.Printf("Input JSON file '%s' does not exist.\n", inputJson)
		os.Exit(1)
	}

	// Process the input json
	ReadInput(s, testDefinitions)

	// Perform specified test cases
	for i := range testDefinitions.TestCases {

		if testDefinitions.TestCases[i].Disabled {
			fmt.Printf("\nSkipping disabled test '%s'\n", testDefinitions.TestCases[i].Name)
			continue
		}

		RunTest(&testDefinitions.TestCases[i])
		fmt.Printf("\nRunning checks on output\n")
		success, err := CheckResults(&testDefinitions.TestCases[i])
		if err != nil {
			fmt.Printf("Error running test case : %s\n", err)
			os.Exit(1)
		}
		if !success {
			fmt.Printf("Test result failed\n")
			os.Exit(1)
		} else {
			fmt.Printf("\nTest '%s' successful\n", testDefinitions.TestCases[i].Name)
		}

	}

	fmt.Printf("\nCongratulations, all tests passed!\n\n")

	// For debugging, just dump the output
	//fmt.Printf("%+v\n", testDefinitions)
}

// fileExists returns true if the specified file exists and is not a directory
func fileExists(filename string) bool {
	info, err := os.Stat(filename)
	if os.IsNotExist(err) {
		return false
	}
	return !info.IsDir()
}

func OrderedToStringMap(input orderedmap.OrderedMap) map[string]string {
	result := make(map[string]string)

	mapKeys := input.Keys()
	for _, bodyKey := range mapKeys {
		if bodyVal, ok := input.Get(bodyKey); ok {
			switch vType := bodyVal.(type) {
			case string:
				result[bodyKey] = bodyVal.(string)
			case bool:
				result[bodyKey] = strconv.FormatBool(bodyVal.(bool))
			default:
				fmt.Printf("OrderedToStringMap received unexpected value type, %T\n", vType)
			}
		}
	}

	return result
}

func OrderedToStringSlice(input []interface{}) []string {
	result := []string{}

	for i := range input {

		switch vType := input[i].(type) {
		// TODO : more types
		case string:
			result = append(result, input[i].(string))
		default:
			fmt.Printf("OrderedToStringSlice received unexpected value type, %T\n", vType)
		}
	}

	return result
}
