/*
 * Copyright 2018-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 core

import (
	"context"
	"crypto/md5"
	"encoding/hex"
	"errors"
	"fmt"
	"gerrit.opencord.org/voltha-bbsim/common/logger"
	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"net"
	"sync"
)

type clientState int

const (
	EAP_START clientState = iota + 1 //TODO: This state definition should support 802.1X
	EAP_RESPID
	EAP_RESPCHA
	EAP_SUCCESS
)

type eapResponder struct {
	clients map[clientKey]*eapClientInstance
	eapolIn chan *byteMsg
}

type clientInstance interface {
	transitState(cur clientState, recvbytes []byte) (next clientState, sendbytes []byte, err error)
	getState() clientState
	getKey() clientKey
}

type eapClientInstance struct {
	key      clientKey
	srcaddr  *net.HardwareAddr
	version  uint8
	curId    uint8
	curState clientState
}

type clientKey struct {
	intfid uint32
	onuid  uint32
}

var resp *eapResponder
var once sync.Once

func getEAPResponder() *eapResponder {
	once.Do(func() {
		resp = &eapResponder{clients: make(map[clientKey]*eapClientInstance), eapolIn: nil}
	})
	return resp
}

//RunEapolResponder starts go routine which processes and responds for received eapol messages
func RunEapolResponder(ctx context.Context, eapolOut chan *byteMsg, eapolIn chan *byteMsg, errch chan error) {
	responder := getEAPResponder()
	responder.eapolIn = eapolIn

	go func() {
		logger.Debug("EAPOL response process starts")
		defer logger.Debug("EAPOL response process was done")
		for {
			select {
			case msg := <- eapolOut:
				logger.Debug("Received eapol from eapolOut intfid:%d onuid:%d", msg.IntfId, msg.OnuId)
				responder := getEAPResponder()
				clients := responder.clients
				if c, ok := clients[clientKey{intfid: msg.IntfId, onuid: msg.OnuId}]; ok {
					logger.Debug("Got client intfid:%d onuid: %d", c.key.intfid, c.key.onuid)
					nextstate := respondMessage("EAPOL", *c, msg, eapolIn)
					c.updateState(nextstate)
				} else {
					logger.Error("Failed to find eapol client instance intfid:%d onuid:%d", msg.IntfId, msg.OnuId)
				}
			case <-ctx.Done():
				return
			}
		}
	}()
}

func respondMessage(msgtype string, client clientInstance, recvmsg *byteMsg, msgInCh chan *byteMsg) clientState {
	curstate := client.getState()
	nextstate, sendbytes, err := client.transitState(curstate, recvmsg.Byte)

	if err != nil {
		msg := fmt.Sprintf("Failed to transitState in %s: %s", msgtype, err)
		logger.Error(msg, err)
	}

	if sendbytes != nil {
		key := client.getKey()
		if err := sendBytes(key, sendbytes, msgInCh); err != nil {
			msg := fmt.Sprintf("Failed to sendBytes in %s: %s", msgtype, err)
			logger.Error(msg)
		}
	} else {
		logger.Debug("sendbytes is nil")
	}
	return nextstate
}

func startEAPClient(intfid uint32, onuid uint32) error {
	client := eapClientInstance{key: clientKey{intfid: intfid, onuid: onuid},
		srcaddr:  &net.HardwareAddr{0x2e, 0x60, 0x70, 0x13, 0x07, byte(onuid)},
		version:  1,
		curId:    0,
		curState: EAP_START}

	eap := client.createEAPStart()
	bytes := client.createEAPOL(eap)
	resp := getEAPResponder()
	eapolIn := resp.eapolIn
	if err := sendBytes(clientKey{intfid, onuid}, bytes, eapolIn); err != nil {
		return errors.New("Failed to send EAPStart")
	}
	logger.Debug("Sending EAPStart")
	//clients[key{intfid: intfid, onuid: onuid}] = &client
	resp.clients[clientKey{intfid: intfid, onuid: onuid}] = &client
	return nil
}

func (c eapClientInstance) transitState(cur clientState, recvbytes []byte) (next clientState, respbytes []byte, err error) {
	recvpkt := gopacket.NewPacket(recvbytes, layers.LayerTypeEthernet, gopacket.Default)
	eap, err := extractEAP(recvpkt)
	if err != nil {
		return cur, nil, nil
	}
	if eap.Code == layers.EAPCodeRequest && eap.Type == layers.EAPTypeIdentity {
		logger.Debug("Received EAP-Request/Identity")
		logger.Debug(recvpkt.Dump())
		c.curId = eap.Id
		if cur == EAP_START {
			reseap := c.createEAPResID()
			pkt := c.createEAPOL(reseap)
			return EAP_RESPID, pkt, nil
		}
	} else if eap.Code == layers.EAPCodeRequest && eap.Type == layers.EAPTypeOTP {
		logger.Debug("Received EAP-Request/Challenge")
		logger.Debug(recvpkt.Dump())
		if cur == EAP_RESPID {
			c.curId = eap.Id
			senddata := getMD5Data(c.curId, eap)
			senddata = append([]byte{0x10}, senddata...)
			sendeap := c.createEAPResCha(senddata)
			pkt := c.createEAPOL(sendeap)
			return EAP_RESPCHA, pkt, nil
		}
	} else if eap.Code == layers.EAPCodeSuccess && eap.Type == layers.EAPTypeNone {
		logger.Debug("Received EAP-Success")
		logger.Debug(recvpkt.Dump())
		if cur == EAP_RESPCHA {
			return EAP_SUCCESS, nil, nil
		}
	} else {
		logger.Debug("Received unsupported EAP")
		return cur, nil, nil
	}
	logger.Debug("State transition does not support..current state:%d", cur)
	logger.Debug(recvpkt.Dump())
	return cur, nil, nil
}

func (c eapClientInstance) getState() clientState {
	return c.curState
}

func (c *eapClientInstance) updateState(state clientState) {
	msg := fmt.Sprintf("EAP update state intfid:%d onuid:%d state:%d", c.key.intfid, c.key.onuid, state)
	logger.Debug(msg)
	c.curState = state
}

func (c eapClientInstance) getKey() clientKey {
	return c.key
}

func sendBytes(key clientKey, pkt []byte, chIn chan *byteMsg) error {
	// Send our packet
	msg := byteMsg{IntfId: key.intfid,
		OnuId: key.onuid,
		Byte:  pkt}
	chIn <- &msg
	logger.Debug("sendBytes intfid:%d onuid:%d", key.intfid, key.onuid)
	logger.Debug(hex.Dump(msg.Byte))
	return nil
}

func (c *eapClientInstance) createEAPOL(eap *layers.EAP) []byte {
	buffer := gopacket.NewSerializeBuffer()
	options := gopacket.SerializeOptions{}

	ethernetLayer := &layers.Ethernet{
		SrcMAC:       *c.srcaddr,
		DstMAC:       net.HardwareAddr{0x01, 0x80, 0xC2, 0x00, 0x00, 0x03},
		EthernetType: layers.EthernetTypeEAPOL,
	}

	if eap == nil { // EAP Start
		gopacket.SerializeLayers(buffer, options,
			ethernetLayer,
			&layers.EAPOL{Version: c.version, Type: 1, Length: 0},
		)
	} else {
		gopacket.SerializeLayers(buffer, options,
			ethernetLayer,
			&layers.EAPOL{Version: c.version, Type: 0, Length: eap.Length},
			eap,
		)
	}
	bytes := buffer.Bytes()
	return bytes
}

func (c *eapClientInstance) createEAPStart() *layers.EAP {
	return nil
}

func (c *eapClientInstance) createEAPResID() *layers.EAP {
	eap := layers.EAP{Code: layers.EAPCodeResponse,
		Id:       c.curId,
		Length:   9,
		Type:     layers.EAPTypeIdentity,
		TypeData: []byte{0x75, 0x73, 0x65, 0x72}}
	return &eap
}

func (c *eapClientInstance) createEAPResCha(payload []byte) *layers.EAP {
	eap := layers.EAP{Code: layers.EAPCodeResponse,
		Id: c.curId, Length: 22,
		Type:     layers.EAPTypeOTP,
		TypeData: payload}
	return &eap
}

func getMD5Data (id uint8, eap *layers.EAP) []byte {
	i := byte(id)
	C := []byte(eap.BaseLayer.Contents)[6:]
	P := []byte{i, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64} //"password"
	data := md5.Sum(append(P, C...))
	ret := make([]byte, 16)
	for j := 0; j < 16; j++ {
		ret[j] = data[j]
	}
	return ret
}

func extractEAPOL(pkt gopacket.Packet) (*layers.EAPOL, error) {
	layerEAPOL := pkt.Layer(layers.LayerTypeEAPOL)
	eapol, _ := layerEAPOL.(*layers.EAPOL)
	if eapol == nil {
		return nil, errors.New("Cannot extract EAPOL")
	}
	return eapol, nil
}

func extractEAP(pkt gopacket.Packet) (*layers.EAP, error) {
	layerEAP := pkt.Layer(layers.LayerTypeEAP)
	eap, _ := layerEAP.(*layers.EAP)
	if eap == nil {
		return nil, errors.New("Cannot extract EAP")
	}
	return eap, nil
}
