/*
 * Copyright 2018-present Open Networking Foundation

 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at

 * http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// The template for the tester.
// This template is filled in by the
// test driver based on the configuration.

package main

import (
	"os"
	"fmt"
	//slog "log"
	"io/ioutil"
	"encoding/json"
	//"google.golang.org/grpc/grpclog"
	"github.com/opencord/voltha-lib-go/v3/pkg/log"
)

type TestCase struct {
	Title string `json:"title"`
	Result bool `json:"passed"`
	Info []string `json:"info"`
}

type TestSuite struct {
	Name string `json:"name"`
	Info []string `json:"info"`
	TestCases []TestCase `json:"testCases"`
}

type TestRun struct {
	TestSuites []TestSuite
}

func (tr * TestRun) testLog(format string, a ...interface{}) {

	tridx := len(tr.TestSuites) - 1
	tcidx := len(tr.TestSuites[tridx].TestCases) - 1

	tr.TestSuites[tridx].TestCases[tcidx].Info =
			append(tr.TestSuites[tridx].TestCases[tcidx].Info, fmt.Sprintf(format, a...))

}

func (tr * TestRun) suiteLog(format string, a ...interface{}) {

	tridx := len(tr.TestSuites) - 1

	tr.TestSuites[tridx].Info =
			append(tr.TestSuites[tridx].Info, fmt.Sprintf(format, a...))

}

func readStats(statFn string) (*TestRun, error) {
	// Check if the  stats file exists
	if _,err := os.Stat(statFn); err != nil {
		// Nothing to do, just return
		return &TestRun{}, nil
	}
	rtrn := &TestRun{}
	// The file is there, read it an unmarshal it into the stats struct
	if statBytes, err := ioutil.ReadFile(statFn); err != nil {
		log.Error(err)
		return nil, err
	} else if err := json.Unmarshal(statBytes, rtrn); err != nil {
		log.Error(err)
		return nil, err
	}
	return rtrn, nil
}

func writeStats(statFn string, stats * TestRun) error {
	// Check if the  stats file exists
	// The file is there, read it an unmarshal it into the stats struct
	if statBytes, err := json.MarshalIndent(stats, "","    "); err != nil {
		log.Error(err)
		return err
	} else if err := ioutil.WriteFile(statFn+".new", statBytes, 0644); err != nil {
		log.Error(err)
		return err
	}
	if err := os.Rename(statFn, statFn+"~"); err != nil {
		log.Error(err)
		return err
	}
	if err := os.Rename(statFn+".new", statFn); err != nil {
		log.Error(err)
		return err
	}
	return nil
}

func (tr * TestRun) appendNew() {
	tr.TestSuites = append(tr.TestSuites, TestSuite{})
}

func initStats(statFn string) error {
	s := &TestRun{}

	if statBytes, err := json.MarshalIndent(s, "","    "); err != nil {
		log.Error(err)
		return err
	} else if err := ioutil.WriteFile(statFn, statBytes, 0644); err != nil {
		log.Error(err)
		return err
	}

	return nil
}


var statFn string
var stats *TestRun
