package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"

	"github.com/iancoleman/orderedmap"
)

// Initial concept from https://stackoverflow.com/q/68621039

func main() {
	parentNode := "input"
	s, err := ioutil.ReadFile("test.json")
	if err != nil {
		panic(err)
	}

	//TestUnmarshalJSON()

	o := orderedmap.New()
	err = json.Unmarshal([]byte(s), &o)
	if err != nil {
		fmt.Printf("JSON Unmarshal error", err)
	}

	// Get a reference to the top level node we specified earlier
	// TODO - validate this key exists
	vislice, ok := o.Get(parentNode)
	if !ok {
		fmt.Printf("Missing key for multitype array")
	}
	vslice := vislice.([]interface{})

	// Get the keys for the first element so we know what the column names will be
	columnMap := vslice[0].(orderedmap.OrderedMap)
	columnNames := columnMap.Keys()
	fmt.Printf("Creating excel workbook with following headings : '%v'\n", columnNames)

	for i, v := range vslice {
		// Print the contents each slice
		//fmt.Printf("'%d' : '%v'\n", i, v)

		fmt.Printf("Slice element %d\n", i)

		// Print each key-value pair contained in this slice
		vmap := v.(orderedmap.OrderedMap)
		k := vmap.Keys()
		for j := range k {
			e, _ := vmap.Get(k[j])
			fmt.Printf("'%s' : '%v'\n", k[j], e)
		}
		//fmt.Printf("k: %v\n", k)
	}

	/*
		//Test https://gitlab.com/c0b/go-ordered-json
		var om *ordered.OrderedMap = ordered.NewOrderedMap()
		err = json.Unmarshal([]byte(file), om)
		if err != nil {
			fmt.Printf("error: '%s'\n", err)
		}

		iter := om.EntriesIter()
		for {
			pair, ok := iter()
			if !ok {
				break
			}
			fmt.Printf("%-12s: %v\n", pair.Key, pair.Value)
		}
	*/

	/*
	   var data interface{}
	   json.Unmarshal(file, &data) // reading all json data
	   //fmt.Println(data)
	   t, ok := data.([]interface{}) // assertion Interface
	   _ = ok
	   //fmt.Printf("%[1]v  %[1]T\n", t) //map[string]interface {}

	   myMap := t[0] // aim here to get APP, Company and Category which will be the column name of Excel sheet
	   fmt.Printf("myMap: %v\n", myMap)
	   columnData, _ := myMap.(map[string]interface{}) // extract the underlying concrete data from interface
	   fmt.Printf("columnData: %v\n", columnData)
	   keys := make([]string, 0, len(columnData)) // creating and initializing slice to store column

	   	for k := range columnData {
	   		fmt.Printf("%[1]v %[1]T\n", k)
	   		keys = append(keys, k)
	   	}

	   return

	   xlsx := excelize.NewFile()
	   sheetName := "Sheet1"
	   xlsx.SetSheetName(xlsx.GetSheetName(1), sheetName)
	   c := 'A'
	   asciiValue := int(c)
	   var a string

	   	for i := 0; i < len(keys); i++ {
	   		a = string(asciiValue)
	   		xlsx.SetCellValue(sheetName, a+"1", keys[i])
	   		asciiValue++
	   	}

	   err = xlsx.SaveAs("./Onkar.xlsx")

	   	if err != nil {
	   		fmt.Println(err)
	   		return
	   	}

	   fmt.Println("Excel file generated sucessfully")
	*/
}

func TestUnmarshalJSON() {
	s := `{
  "number": 4,
  "string": "x",
  "z": 1,
  "a": "should not break with unclosed { character in value",
  "b": 3,
  "slice": [
    "1",
    1
  ],
  "orderedmap": {
    "e": 1,
    "a { nested key with brace": "with a }}}} }} {{{ brace value",
	"after": {
		"link": "test {{{ with even deeper nested braces }"
	}
  },
  "test\"ing": 9,
  "after": 1,
  "multitype_array": [
    "test",
	1,
	{ "map": "obj", "it" : 5, ":colon in key": "colon: in value" },
	[{"inner": "map"}]
  ],
  "should not break with { character in key": 1
}`
	o := orderedmap.New()
	err := json.Unmarshal([]byte(s), &o)
	if err != nil {
		fmt.Printf("JSON Unmarshal error", err)
	}
	// Check the root keys
	expectedKeys := []string{
		"number",
		"string",
		"z",
		"a",
		"b",
		"slice",
		"orderedmap",
		"test\"ing",
		"after",
		"multitype_array",
		"should not break with { character in key",
	}
	k := o.Keys()
	for i := range k {
		if k[i] != expectedKeys[i] {
			fmt.Printf("Unmarshal root key order", i, k[i], "!=", expectedKeys[i])
		}
	}
	// Check nested maps are converted to orderedmaps
	// nested 1 level deep
	expectedKeys = []string{
		"e",
		"a { nested key with brace",
		"after",
	}
	vi, ok := o.Get("orderedmap")
	if !ok {
		fmt.Printf("Missing key for nested map 1 deep")
	}
	v := vi.(orderedmap.OrderedMap)
	k = v.Keys()
	for i := range k {
		if k[i] != expectedKeys[i] {
			fmt.Printf("Key order for nested map 1 deep ", i, k[i], "!=", expectedKeys[i])
		}
	}
	// nested 2 levels deep
	expectedKeys = []string{
		"link",
	}
	vi, ok = v.Get("after")
	if !ok {
		fmt.Printf("Missing key for nested map 2 deep")
	}
	v = vi.(orderedmap.OrderedMap)
	k = v.Keys()
	for i := range k {
		if k[i] != expectedKeys[i] {
			fmt.Printf("Key order for nested map 2 deep", i, k[i], "!=", expectedKeys[i])
		}
	}
	// multitype array
	expectedKeys = []string{
		"map",
		"it",
		":colon in key",
	}
	vislice, ok := o.Get("multitype_array")
	if !ok {
		fmt.Printf("Missing key for multitype array")
	}
	vslice := vislice.([]interface{})
	vmap := vslice[2].(orderedmap.OrderedMap)
	k = vmap.Keys()
	for i := range k {
		if k[i] != expectedKeys[i] {
			fmt.Printf("Key order for nested map 2 deep", i, k[i], "!=", expectedKeys[i])
		}
	}
	// nested map 3 deep
	vislice, _ = o.Get("multitype_array")
	vslice = vislice.([]interface{})
	expectedKeys = []string{"inner"}
	vinnerslice := vslice[3].([]interface{})
	vinnermap := vinnerslice[0].(orderedmap.OrderedMap)
	k = vinnermap.Keys()
	for i := range k {
		if k[i] != expectedKeys[i] {
			fmt.Printf("Key order for nested map 3 deep", i, k[i], "!=", expectedKeys[i])
		}
	}
}
