/*
 * Copyright 2019-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.
 */
package commands

import (
	"bufio"
	b64 "encoding/base64"
	"fmt"
	"github.com/fullstorydev/grpcurl"
	versionUtils "github.com/hashicorp/go-version"
	"github.com/jhump/protoreflect/dynamic"
	"github.com/jhump/protoreflect/grpcreflect"
	corderrors "github.com/opencord/cordctl/error"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	reflectpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
	"log"
	"os"
	"strings"
)

// Flags for calling the InitReflectionClient Method
const (
	INIT_DEFAULT          = 0
	INIT_NO_VERSION_CHECK = 1 // Do not check whether server is allowed version
)

func GenerateHeaders() []string {
	username := GlobalConfig.Username
	password := GlobalConfig.Password
	sEnc := b64.StdEncoding.EncodeToString([]byte(username + ":" + password))
	headers := []string{"authorization: basic " + sEnc}
	return headers
}

// Perform the GetVersion API call on the core to get the version
func GetVersion(conn *grpc.ClientConn, descriptor grpcurl.DescriptorSource) (*dynamic.Message, error) {
	ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
	defer cancel()

	headers := GenerateHeaders()

	h := &RpcEventHandler{}
	err := grpcurl.InvokeRPC(ctx, descriptor, conn, "xos.utility.GetVersion", headers, h, h.GetParams)
	if err != nil {
		return nil, corderrors.RpcErrorToCordError(err)
	}

	if h.Status != nil && h.Status.Err() != nil {
		return nil, corderrors.RpcErrorToCordError(h.Status.Err())
	}

	d, err := dynamic.AsDynamicMessage(h.Response)

	return d, err
}

// Initialize client connection
//    flags is a set of optional flags that may influence how the connection is setup
//        INIT_DEFAULT - default behavior (0)
//        INIT_NO_VERSION_CHECK - do not perform core version check

func InitClient(flags uint32) (*grpc.ClientConn, grpcurl.DescriptorSource, error) {
	conn, err := NewConnection()
	if err != nil {
		return nil, nil, err
	}

	refClient := grpcreflect.NewClient(context.Background(), reflectpb.NewServerReflectionClient(conn))
	defer refClient.Reset()

	// Intended method of use is to download the protos via reflection API. Loading the
	// protos from a file is supported for unit testing, as the mock server does not
	// support the reflection API.

	var descriptor grpcurl.DescriptorSource
	if GlobalConfig.Protoset != "" {
		descriptor, err = grpcurl.DescriptorSourceFromProtoSets(GlobalConfig.Protoset)
		if err != nil {
			return nil, nil, err
		}
	} else {
		descriptor = grpcurl.DescriptorSourceFromServer(context.Background(), refClient)
	}

	if flags&INIT_NO_VERSION_CHECK == 0 {
		d, err := GetVersion(conn, descriptor)
		if err != nil {
			return nil, nil, err
		}
		// Note: NewVersion doesn't like the `-dev` suffix, so strip it off.
		serverVersion, err := versionUtils.NewVersion(strings.Split(d.GetFieldByName("version").(string), "-")[0])
		if err != nil {
			return nil, nil, err
		}

		constraint, err := versionUtils.NewConstraint(CORE_VERSION_CONSTRAINT)
		if err != nil {
			return nil, nil, err
		}

		if !constraint.Check(serverVersion) {
			return nil, nil, corderrors.WithStackTrace(&corderrors.VersionConstraintError{
				Name:       "xos-core",
				Version:    serverVersion.String(),
				Constraint: CORE_VERSION_CONSTRAINT})
		}

	}

	return conn, descriptor, nil
}

// A makeshift substitute for C's Ternary operator
func Ternary_uint32(condition bool, value_true uint32, value_false uint32) uint32 {
	if condition {
		return value_true
	} else {
		return value_false
	}
}

// call printf only if visible is True
func conditional_printf(visible bool, format string, args ...interface{}) {
	if visible {
		fmt.Printf(format, args...)
	}
}

// Print a confirmation prompt and get a response from the user
func Confirmf(format string, args ...interface{}) bool {
	if GlobalOptions.Yes {
		return true
	}

	reader := bufio.NewReader(os.Stdin)

	for {
		msg := fmt.Sprintf(format, args...)
		fmt.Print(msg)

		response, err := reader.ReadString('\n')
		if err != nil {
			log.Fatal(err)
		}

		response = strings.ToLower(strings.TrimSpace(response))

		if response == "y" || response == "yes" {
			return true
		} else if response == "n" || response == "no" {
			return false
		}
	}
}
