/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 parsers

import (
	"encoding/json"
	"fmt"
	"github.com/apache/incubator-openwhisk-wskdeploy/utils"
	"github.com/apache/incubator-openwhisk-wskdeploy/wskderrors"
	"github.com/apache/incubator-openwhisk-wskdeploy/wskenv"
	"reflect"
)

// TODO(): Support other valid Package Manifest types
// TODO(): i.e., timestamp, version, string256, string64, string16
// TODO(): Support JSON schema validation for type: json
// TODO(): Support OpenAPI schema validation
const (
	STRING  string = "string"
	INTEGER string = "integer"
	FLOAT   string = "float"
	BOOLEAN string = "boolean"
	JSON    string = "json"
)

var validParameterNameMap = map[string]string{
	STRING:    STRING,
	FLOAT:     FLOAT,
	BOOLEAN:   BOOLEAN,
	INTEGER:   INTEGER,
	"int":     INTEGER,
	"bool":    BOOLEAN,
	"int8":    INTEGER,
	"int16":   INTEGER,
	"int32":   INTEGER,
	"int64":   INTEGER,
	"float32": FLOAT,
	"float64": FLOAT,
	JSON:      JSON,
	"map":     JSON,
}

var typeDefaultValueMap = map[string]interface{}{
	STRING:  "",
	INTEGER: 0,
	FLOAT:   0.0,
	BOOLEAN: false,
	JSON:    make(map[string]interface{}),
	// TODO() Support these types + their validation
	// timestamp
	// null
	// version
	// string256
	// string64
	// string16
	// scalar-unit
	// schema
	// object
}

func isValidParameterType(typeName string) bool {
	_, isValid := typeDefaultValueMap[typeName]
	return isValid
}

// TODO(): throw errors
func getTypeDefaultValue(typeName string) interface{} {

	if val, ok := typeDefaultValueMap[typeName]; ok {
		return val
	} else {
		// TODO() throw an error "type not found" InvalidParameterType
	}
	return nil
}

func IsTypeDefaultValue(typeName string, value interface{}) bool {
	defaultValue := getTypeDefaultValue(typeName)
	if defaultValue == nil {
		return false
	} else if defaultValue == value {
		return true
	}
	return false
}

/*
   ResolveParamTypeFromValue Resolves the Parameter's data type from its actual value.

   Inputs:
   - paramName: name of the parameter for error reporting
   - filepath: the path, including name, of the YAML file which contained the parameter for error reporting
   - value: the parameter value to resolve

   Returns:
   - (string) parameter type name as a string
*/
func ResolveParamTypeFromValue(paramName string, value interface{}, filePath string) (string, error) {
	// Note: 'string' is the default type if not specified and not resolvable.
	var paramType string = "string"
	var err error = nil

	if value != nil {
		actualType := reflect.TypeOf(value).Kind().String()

		// See if the actual type of the value is valid
		if normalizedTypeName, found := validParameterNameMap[actualType]; found {
			// use the full spec. name
			paramType = normalizedTypeName

		} else {
			// raise an error if parameter's value is not a known type
			err = wskderrors.NewInvalidParameterTypeError(filePath, paramName, actualType)
		}
	}
	return paramType, err
}

/*
   resolveSingleLineParameter assures that a Parameter's Type is correctly identified and set from its Value.

   Additionally, this function:

   - detects if the parameter value contains the name of a valid OpenWhisk parameter types. if so, the
     - param.Type is set to detected OpenWhisk parameter type.
     - param.Value is set to the zero (default) value for that OpenWhisk parameter type.

   Inputs:
   - filePath: the path, including name, of the YAML file which contained the parameter for error reporting
   - paramName: name of the parameter for error reporting
   - param: pointer to Parameter structure being resolved

   Returns:
   - (interface{}) the parameter's resolved value
*/
func resolveSingleLineParameter(filePath string, paramName string, param *Parameter) (interface{}, error) {
	var errorParser error

	if !param.multiline {
		// We need to identify parameter Type here for later validation
		param.Type, errorParser = ResolveParamTypeFromValue(paramName, param.Value, filePath)

		// In single-line format, the param's <value> can be a "Type name" and NOT an actual value.
		// if this is the case, we must detect it and set the value to the default for that type name.
		if param.Value != nil && param.Type == "string" {
			// The value is a <string>; now we must test if is the name of a known Type
			if isValidParameterType(param.Value.(string)) {
				// If the value is indeed the name of a Type, we must change BOTH its
				// Type to be that type and its value to that Type's default value
				param.Type = param.Value.(string)
				param.Value = getTypeDefaultValue(param.Type)
				//fmt.Printf("EXIT: Parameter [%s] type=[%v] value=[%v]\n", paramName, param.Type, param.Value)
			}
		}

	} else {
		// TODO() - move string to i18n
		return param.Value, wskderrors.NewYAMLParserErr(filePath,
			"Parameter ["+paramName+"] is not single-line format.")
	}

	return param.Value, errorParser
}

/*
   resolveMultiLineParameter assures that the values for Parameter Type and Value are properly set and are valid.

   Additionally, this function:
   - uses param.Default as param.Value if param.Value is not provided
   - uses the actual param.Value data type for param.type if param.Type is not provided

   Inputs:
   - filepath: the path, including name, of the YAML file which contained the parameter for error reporting
   - paramName: name of the parameter for error reporting
   - param: pointer to Parameter structure being resolved

   Returns:
   - (interface{}) the parameter's resolved value

*/
func resolveMultiLineParameter(filePath string, paramName string, param *Parameter) (interface{}, error) {
	var errorParser error

	if param.multiline {
		var valueType string

		// if we do not have a value, but have a default, use it for the value
		if param.Value == nil && param.Default != nil {
			param.Value = param.Default
		}

		// Note: if either the value or default is in conflict with the type then this is an error
		valueType, errorParser = ResolveParamTypeFromValue(paramName, param.Value, filePath)

		// if we have a declared parameter Type, assure that it is a known value
		if param.Type != "" {
			if !isValidParameterType(param.Type) {
				// TODO() - move string to i18n
				return param.Value, wskderrors.NewYAMLParserErr(filePath,
					"Parameter ["+paramName+"] has an invalid Type. ["+param.Type+"]")
			}
		} else {
			// if we do not have a value for the Parameter Type, use the Parameter Value's Type
			param.Type = valueType
		}

		// TODO{} if the declared and actual parameter type conflict, generate TypeMismatch error
		//if param.Type != valueType{
		//	errorParser = utils.NewParameterTypeMismatchError("", param.Type, valueType )
		//}
	} else {
		// TODO() - move string to i18n
		return param.Value, wskderrors.NewYAMLParserErr(filePath,
			"Parameter ["+paramName+"] is not multiline format.")
	}

	return param.Value, errorParser
}

/*
   resolveJSONParameter assure JSON data is converted to a map[string]{interface*} type.

   This function handles the forms JSON data appears in:
   1) a string containing JSON, which needs to be parsed into map[string]interface{}
   2) is a map of JSON (but not a map[string]interface{}

   Inputs:
   - paramName: name of the parameter for error reporting
   - filePath: the path, including name, of the YAML file which contained the parameter for error reporting
   - param: pointer to Parameter structure being resolved
   - value: the current actual value of the parameter being resolved

   Returns:
   - (interface{}) the parameter's resolved value
*/
func resolveJSONParameter(filePath string, paramName string, param *Parameter, value interface{}) (interface{}, error) {
	var errorParser error

	// TODO() Is the "value" function parameter really needed with the current logic (use param.Value)?
	if param.Type == "json" {
		// Case 1: if user set parameter type to 'json' and the value's type is a 'string'
		if str, ok := value.(string); ok {
			var parsed interface{}
			errParser := json.Unmarshal([]byte(str), &parsed)
			if errParser == nil {
				//fmt.Printf("EXIT: Parameter [%s] type=[%v] value=[%v]\n", paramName, param.Type, parsed)
				return parsed, errParser
			}
		}

		// Case 2: value contains a map of JSON
		// We must make sure the map type is map[string]interface{}; otherwise we cannot
		// marshall it later on to serialize in the body of an HTTP request.
		if param.Value != nil && reflect.TypeOf(param.Value).Kind() == reflect.Map {
			if _, ok := param.Value.(map[interface{}]interface{}); ok {
				var temp map[string]interface{} = utils.ConvertInterfaceMap(param.Value.(map[interface{}]interface{}))
				for name, val := range temp {
					temp[name] = wskenv.InterpolateStringWithEnvVar(val)
				}
				//fmt.Printf("EXIT: Parameter [%s] type=[%v] value=[%v]\n", paramName, param.Type, temp)
				return temp, errorParser
			}
		} else {
			errorParser = wskderrors.NewParameterTypeMismatchError(filePath, paramName, JSON, param.Type)
		}

	} else {
		// TODO() - move string to i18n
		errorParser = wskderrors.NewYAMLParserErr(filePath, "Parameter ["+paramName+"] is not JSON format.")
	}

	return param.Value, errorParser
}

/*
   ResolveParameter assures that the Parameter structure's values are correctly filled out for
   further processing.  This includes special processing for

   - single-line format parameters
     - deriving missing param.Type from param.Value
     - resolving case where param.Value contains a valid Parameter type name
   - multi-line format parameters:
     - assures that param.Value is set while taking into account param.Default
     - validating param.Type

   Note: parameter values may set later (overridden) by an (optional) Deployment file

   Inputs:
   - paramName: name of the parameter for error reporting
   - filepath: the path, including name, of the YAML file which contained the parameter for error reporting
   - param: pointer to Parameter structure being resolved

   Returns:
   - (interface{}) the parameter's resolved value
*/
func ResolveParameter(paramName string, param *Parameter, filePath string) (interface{}, error) {

	var errorParser error
	// default resolved parameter value to empty string
	var value interface{} = ""

	// Trace Parameter struct before any resolution
	//dumpParameter(paramName, param, "BEFORE")

	// Parameters can be single OR multi-line declarations which must be processed/validated differently
	// Regardless, the following functions will assure that param.Value and param.Type are correctly set
	if !param.multiline {
		value, errorParser = resolveSingleLineParameter(filePath, paramName, param)

	} else {
		value, errorParser = resolveMultiLineParameter(filePath, paramName, param)
	}

	// String value pre-processing (interpolation)
	// See if we have any Environment Variable replacement within the parameter's value

	// Make sure the parameter's value is a valid, non-empty string
	if param.Value != nil && param.Type == "string" {
		// perform $ notation replacement on string if any exist
		value = wskenv.InterpolateStringWithEnvVar(param.Value)
	}

	// JSON - Handle both cases, where value 1) is a string containing JSON, 2) is a map of JSON
	if param.Value != nil && param.Type == "json" {
		value, errorParser = resolveJSONParameter(filePath, paramName, param, value)
	}

	// Default value to zero value for the Type
	// Do NOT error/terminate as Value may be provided later by a Deployment file.
	if value == nil {
		value = getTypeDefaultValue(param.Type)
		// @TODO(): Need warning message here to warn of default usage, support for warnings (non-fatal)
		//msgs := []string{"Parameter [" + paramName + "] is not multiline format."}
		//return param.Value, utils.NewParserErr(filePath, nil, msgs)
	}

	// Trace Parameter struct after resolution
	//dumpParameter(paramName, param, "AFTER")
	//fmt.Printf("EXIT: Parameter [%s] type=[%v] value=[%v]\n", paramName, param.Type, value)
	return value, errorParser
}

// Provide custom Parameter marshalling and unmarshalling
type ParsedParameter Parameter

func (n *Parameter) UnmarshalYAML(unmarshal func(interface{}) error) error {
	var aux ParsedParameter

	// Attempt to unmarshal the multi-line schema
	if err := unmarshal(&aux); err == nil {
		n.multiline = true
		n.Type = aux.Type
		n.Description = aux.Description
		n.Value = aux.Value
		n.Required = aux.Required
		n.Default = aux.Default
		n.Status = aux.Status
		n.Schema = aux.Schema
		return nil
	}

	// If we did not find the multi-line schema, assume in-line (or single-line) schema
	var inline interface{}
	if err := unmarshal(&inline); err != nil {
		return err
	}

	n.Value = inline
	n.multiline = false
	return nil
}

func (n *Parameter) MarshalYAML() (interface{}, error) {
	if _, ok := n.Value.(string); len(n.Type) == 0 && len(n.Description) == 0 && ok {
		if !n.Required && len(n.Status) == 0 && n.Schema == nil {
			return n.Value.(string), nil
		}
	}

	return n, nil
}

// Provides debug/trace support for Parameter type
func dumpParameter(paramName string, param *Parameter, separator string) {

	fmt.Printf("%s:\n", separator)
	fmt.Printf("\t%s: (%T)\n", paramName, param)
	if param != nil {
		fmt.Printf("\t\tParameter.Description: [%s]\n", param.Description)
		fmt.Printf("\t\tParameter.Type: [%s]\n", param.Type)
		fmt.Printf("\t\t--> Actual Type: [%T]\n", param.Value)
		fmt.Printf("\t\tParameter.Value: [%v]\n", param.Value)
		fmt.Printf("\t\tParameter.Default: [%v]\n", param.Default)
	}
}
