/*
* Copyright 2022-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 nbi

import (
	"encoding/json"
	"net"
	"net/http"
	"strconv"
	"time"

	app "voltha-go-controller/internal/pkg/application"
	"voltha-go-controller/log"

	"github.com/gorilla/mux"
)

// DHCPSessionInfoHandle handle dhcp session Requests
type DHCPSessionInfoHandle struct {
}

// DhcpSessionInfo Information
type DhcpSessionInfo struct {
	DeviceID    string
	Uniport     string
	Svlan       string
	Cvlan       string
	UniVlan     string
	MacAddress  string
	IPAddress   string
	Ipv6Address string
	State       string
	Statev6     string
	LeaseTime   string
	LeaseTimev6 string
}

// getDhcpSessionFields returns dhcp session information
func getDhcpSessionFields(id string, port string, svlan string, cvlan string, univlan string, macAddr string, ipAddr net.IP, ipv6Addr net.IP, rState app.DhcpRelayState, rStatev6 app.Dhcpv6RelayState, lTime time.Time, l6Time time.Time) *DhcpSessionInfo {
	ip := ipAddr.String()
	ipv6 := ipv6Addr.String()
	relayState := strconv.Itoa(int(rState))
	relayStatev6 := strconv.Itoa(int(rStatev6))
	leaseTime := (lTime.Format(time.RubyDate))
	leasev6Time := (l6Time.Format(time.RubyDate))
	dInfo := &DhcpSessionInfo{DeviceID: id, Uniport: port, Svlan: svlan, Cvlan: cvlan, UniVlan: univlan, MacAddress: macAddr, IPAddress: ip, Ipv6Address: ipv6, State: relayState, Statev6: relayStatev6, LeaseTime: leaseTime, LeaseTimev6: leasev6Time}
	return dInfo
}

// validateArgs validate the arguments
func validateArgs(sv string, cv string, macAddr string, svlan string, cvlan string, mac string) bool {
	var vlanFlag bool
	var macFlag bool

	if ((sv == svlan) || (len(svlan) == 0)) && ((cv == cvlan) || (len(cvlan) == 0)) {
		vlanFlag = true
	}

	if mac == macAddr || len(mac) == 0 {
		macFlag = true
	}

	if macFlag && vlanFlag {
		return true
	}
	return false
}

// serveHTTP for actions performed on API.
func (dh *DHCPSessionInfoHandle) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	logger.Infow(ctx, "Received-northbound-request", log.Fields{"Method": r.Method, "URL": r.URL})
	switch r.Method {
	case cGet:
		dh.getDhcpSessionInfo(w, r)
	default:
		logger.Warnw(ctx, "Unsupported Method", log.Fields{"Method": r.Method})
	}
}

// getDhcpSessionInfo to retrieve dhcp session information.
func (dh *DHCPSessionInfoHandle) getDhcpSessionInfo(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	id := vars["id"]
	mac := vars["mac"]
	svlan := vars["svlan"]
	cvlan := vars["cvlan"]
	var dhcpData *DhcpSessionInfo

	logger.Infow(ctx, "Received get Dhcp Session Info", log.Fields{"DeviceID": id})

	var voltAppIntr app.VoltAppInterface
	voltApp := app.GetApplication()
	voltAppIntr = voltApp
	dhcpSessionInfoResp := []*DhcpSessionInfo{}

	getPorts := func(key, value interface{}) bool {
		port := key.(string)
		vp := value.(*app.VoltPort)

		// Ignore if UNI port is not UP
		if vp.State != app.PortStateUp {
			logger.Warnw(ctx, "Ignore if UNI port is not UP", log.Fields{"VoltPort State": vp.State, "PortStateUp": app.PortStateUp})
			return true
		}

		// Obtain all VPVs associated with the port
		vnets, ok := voltApp.VnetsByPort.Load(port)
		if !ok {
			return true
		}

		for _, vpv := range vnets.([]*app.VoltPortVnet) {
			// When only device id is provided as argument
			sv := strconv.Itoa(int(vpv.SVlan))
			cv := strconv.Itoa(int(vpv.CVlan))
			uv := strconv.Itoa(int(vpv.UniVlan))
			macAddr := (vpv.MacAddr).String()

			validData := validateArgs(sv, cv, macAddr, svlan, cvlan, mac)

			if validData {
				dhcpData = getDhcpSessionFields(id, vpv.Port, sv, cv, uv, macAddr, vpv.Ipv4Addr, vpv.Ipv6Addr, vpv.RelayState, vpv.RelayStatev6, vpv.DhcpExpiryTime, vpv.Dhcp6ExpiryTime)
				dhcpSessionInfoResp = append(dhcpSessionInfoResp, dhcpData)
			}
		}
		return true
	}

	if len(id) == 0 {
		logger.Warnw(ctx, "No Device Id Provided for Dhcp session Info", log.Fields{"DeviceID": id})
		return
	}
	voltDevice := voltAppIntr.GetDevice(id)
	if voltDevice != nil {
		voltDevice.Ports.Range(getPorts)
	}

	dhcpSessionInfoJSON, err := json.Marshal(dhcpSessionInfoResp)
	if err != nil {
		logger.Errorw(ctx, "Error occurred while marshaling dhcp session info response", log.Fields{"DeviceID": id, "DhcpSessionInfoResp": dhcpSessionInfoResp, "Error": err})
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	w.Header().Add("Content-Type", "application/json")
	_, err = w.Write(dhcpSessionInfoJSON)
	if err != nil {
		logger.Errorw(ctx, "error in sending dhcp session info response", log.Fields{"DeviceID": id, "DhcpSessionInfo": dhcpSessionInfoResp, "Error": err})
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	logger.Debugw(ctx, "Fetching Dhcp Session Info", log.Fields{"DhcpSessionInfo": dhcpSessionInfoResp})
}
