// Copyright 2016 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 main

import (
	"bytes"
	"encoding/json"
	"net/http"
	"strings"
	"text/template"
)

type GenerationOptions struct {
	SwitchCount int `json:"switchcount"`
	HostCount   int `json:"hostcount"`
}

func (c *Config) configGenHandler(w http.ResponseWriter, r *http.Request) {
	var options GenerationOptions

	deviceMap := make(map[string]*onosDevice)

	decoder := json.NewDecoder(r.Body)
	defer r.Body.Close()
	if err := decoder.Decode(&options); err != nil {
		log.Errorf("Unable to decode provisioning request options: %s", err)
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	var devices onosDevices
	err := c.fetch("/onos/v1/devices", &devices)
	if err != nil {
		log.Errorf("Unable to retrieve device information from controller: %s", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// If the request specified the number of switches, validate we have that
	// exact number
	if options.SwitchCount > 0 && len(devices.Devices) != options.SwitchCount {
		log.Errorf("Expecting %d switch(es), found %d, no configuration generated",
			options.SwitchCount, len(devices.Devices))
		http.Error(w, "Expected switch count mismatch",
			http.StatusInternalServerError)
		return
	}

	for _, device := range devices.Devices {
		deviceMap[device.Id] = device
		device.Mac = splitString(device.ChassisId, 2, ":")
	}

	var hosts onosHosts
	err = c.fetch("/onos/v1/hosts", &hosts)
	if err != nil {
		log.Errorf("Unable to retrieve host information from controller: %s", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return

	}

	// If the request specified the number of hosts, validate we have that
	// exact number
	if options.HostCount > 0 && len(hosts.Hosts) != options.HostCount {
		log.Errorf("Expecting %d host(s), found %d, no configuration generated",
			options.HostCount, len(hosts.Hosts))
		http.Error(w, "Expected host count mismatch",
			http.StatusInternalServerError)
		return
	}

	// Use a simple heuristic to determine which switches are edge routers
	// and which are not
	markEdgeRouters(deviceMap, hosts)

	// Generate the configuration file
	cfg := onosConfig{
		Devices: devices.Devices,
		Hosts:   hosts.Hosts,
	}

	funcMap := template.FuncMap{
		// The name "inc" is what the function will be called in the template text.
		"add": func(a, b int) int {
			return a + b
		},
		"gateway": func(ips []string) string {
			if len(ips) > 0 {
				parts := strings.Split(ips[0], ".")
				ip := ""
				for _, v := range parts[:len(parts)-1] {
					ip = ip + v + "."
				}
				return ip + "254/24"
			} else {
				return "0.0.0.254/24"
			}
		},
		"vlan": func(ips []string) string {
			if (len(ips) > 0) {
				return strings.Split(ips[0], ".")[2]
			} else {
				return "0"
			}
		},
	}

	tpl, err := template.New("netconfig.tpl").Funcs(funcMap).ParseFiles("netconfig.tpl")
	if err != nil {
		log.Errorf("Unable to parse template: %s", err)
		http.Error(w, "Template parse error", http.StatusInternalServerError)
		return
	}

	// Write template to buffer, so if there is an error we can return an
	// http error
	buf := new(bytes.Buffer)
	err = tpl.Execute(buf, cfg)
	if err != nil {
		log.Errorf("Unexpected error while processing template: %s", err)
		http.Error(w, "Template processing error", http.StatusInternalServerError)
	}

	w.Write(buf.Bytes())
}

// markEdgeRouters use hueristic to determine and mark switches that act
// as edge routers
func markEdgeRouters(dm map[string]*onosDevice, hosts onosHosts) {
	// Walk the list of know compute nodes (hosts) and if the compute node
	// is connected to a switch, then that switch is an edge router
	for _, host := range hosts.Hosts {
		if device, ok := dm[host.Location.ElementID]; ok {
			(*device).IsEdgeRouter = true
		}
	}
}

// splitString used to convert a string to a psudeo MAC address by
// splitting and separating it with a colon
func splitString(src string, n int, sep string) string {
	r := ""
	for i, c := range src {
		if i > 0 && i%n == 0 {
			r += sep
		}
		r += string(c)
	}
	return r
}

// fetch fetch the specified data from ONOS
func (c *Config) fetch(path string, data interface{}) error {
	resp, err := http.Get(c.connect + path)
	if err != nil {
		return err
	}

	defer resp.Body.Close()
	decoder := json.NewDecoder(resp.Body)
	err = decoder.Decode(data)
	return err
}
