/*
 * 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
}

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
}
