// 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 config

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"sort"
	"strings"
	"unicode"
)

// FAKE is used for fake CLI only options like filter=
const FAKE = "fake"

// APIArg are the args passable to an API
type APIArg struct {
	Name        string
	Type        string
	Related     []string
	Description string
	Required    bool
	Length      int
}

// API describes a CloudStack API
type API struct {
	Name         string
	Verb         string
	Noun         string
	Args         []*APIArg
	RequiredArgs []string
	Related      []string
	Async        bool
	Description  string
	ResponseKeys []string
}

var apiCache map[string]*API
var apiVerbMap map[string][]*API

// GetAPIVerbMap returns API cache by verb
func (c *Config) GetAPIVerbMap() map[string][]*API {
	if apiVerbMap != nil {
		return apiVerbMap
	}
	apiSplitMap := make(map[string][]*API)
	for api := range apiCache {
		verb := apiCache[api].Verb
		apiSplitMap[verb] = append(apiSplitMap[verb], apiCache[api])
	}
	return apiSplitMap
}

// GetCache returns API cache by full API name
func (c *Config) GetCache() map[string]*API {
	if apiCache == nil {
		// read from disk?
		return make(map[string]*API)
	}
	return apiCache
}

// LoadCache loads cache using the default cache file
func LoadCache(c *Config) interface{} {
	cacheFile := c.CacheFile()
	Debug("Trying to read API cache from:", cacheFile)
	cache, err := ioutil.ReadFile(cacheFile)
	if err != nil {
		if c.HasShell {
			fmt.Fprintf(os.Stderr, "Loaded in-built API cache. Failed to read API cache, please run 'sync'.\n")
		}
		cache = []byte(preCache)
	}
	var data map[string]interface{}
	_ = json.Unmarshal(cache, &data)
	return c.UpdateCache(data)
}

// SaveCache saves received auto-discovery data to cache file
func (c *Config) SaveCache(response map[string]interface{}) {
	output, _ := json.Marshal(response)
	ioutil.WriteFile(c.CacheFile(), output, 0600)
}

// UpdateCache uses auto-discovery data to update internal API cache
func (c *Config) UpdateCache(response map[string]interface{}) interface{} {
	apiCache = make(map[string]*API)
	apiVerbMap = nil

	count := response["count"]
	apiList := response["api"].([]interface{})

	for _, node := range apiList {
		api, valid := node.(map[string]interface{})
		if !valid {
			fmt.Println("Error, moving on...")
			continue
		}
		apiName := api["name"].(string)
		isAsync := api["isasync"].(bool)
		description := api["description"].(string)

		idx := 0
		for _, chr := range apiName {
			if unicode.IsLower(chr) {
				idx++
			} else {
				break
			}
		}
		verb := apiName[:idx]
		noun := strings.ToLower(apiName[idx:])

		var apiArgs []*APIArg
		for _, argNode := range api["params"].([]interface{}) {
			apiArg, _ := argNode.(map[string]interface{})
			related := []string{}
			if apiArg["related"] != nil {
				related = strings.Split(apiArg["related"].(string), ",")
				sort.Strings(related)
			}
			apiArgs = append(apiArgs, &APIArg{
				Name:        apiArg["name"].(string) + "=",
				Type:        apiArg["type"].(string),
				Required:    apiArg["required"].(bool),
				Related:     related,
				Description: apiArg["description"].(string),
			})
		}

		// Add filter arg
		apiArgs = append(apiArgs, &APIArg{
			Name:        "filter=",
			Type:        FAKE,
			Description: "cloudmonkey specific response key filtering",
		})

		sort.Slice(apiArgs, func(i, j int) bool {
			return apiArgs[i].Name < apiArgs[j].Name
		})

		var responseKeys []string
		for _, respNode := range api["response"].([]interface{}) {
			if resp, ok := respNode.(map[string]interface{}); ok {
				if resp == nil || resp["name"] == nil {
					continue
				}
				responseKeys = append(responseKeys, fmt.Sprintf("%v,", resp["name"]))
			}
		}
		sort.Strings(responseKeys)

		var requiredArgs []string
		for _, arg := range apiArgs {
			if arg.Required {
				requiredArgs = append(requiredArgs, arg.Name)
			}
		}

		apiCache[strings.ToLower(apiName)] = &API{
			Name:         apiName,
			Verb:         verb,
			Noun:         noun,
			Args:         apiArgs,
			RequiredArgs: requiredArgs,
			Async:        isAsync,
			Description:  description,
			ResponseKeys: responseKeys,
		}
	}
	return count
}
