/*
 * 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"
	"net"
	"sync"
	"time"

	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/opencord/voltha-bbsim/common/logger"
	log "github.com/sirupsen/logrus"
)

type clientState int

// Constants for eapol states
const (
	EapStart clientState = iota + 1 // TODO: This state definition should support 802.1X
	EapRespid
	EapRespcha
	EapSuccess
)

func (eap clientState) String() string {
	return [...]string{"EAP_START", "EAP_RESPID", "EAP_RESPCHA", "EAP_SUCCESS"}[eap]
}

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 (ClientID: %v)", c.key.intfid, c.key.onuid, c.curID)
					nextstate := respondMessage("EAPOL", *c, msg, eapolIn)
					c.updateState(nextstate)
				} else {
					logger.WithFields(log.Fields{
						"clients": clients,
					}).Errorf("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 sendEAPStart(intfid uint32, onuid uint32, client eapClientInstance, bytes []byte, eapolIn chan *byteMsg) error {
	for {
		responder := getEAPResponder()
		clients := responder.clients
		if c, ok := clients[clientKey{intfid: intfid, onuid: onuid}]; ok {
			if c.curState == EapSuccess {
				logger.WithFields(log.Fields{
					"int_id": intfid,
					"onu_id": onuid,
				}).Debug("EAP_SUCCESS received, stop retrying")
				break
			}
			// Reset state to EAP start
			c.updateState(EapStart)
		} else {
			logger.WithFields(log.Fields{
				"clients": clients,
			}).Errorf("Failed to find eapol client instance intfid:%d onuid:%d (sendEAPStart)", intfid, onuid)
		}
		if err := sendBytes(clientKey{intfid, onuid}, bytes, eapolIn); err != nil {
			return errors.New("Failed to send EAPStart")
		}
		logger.WithFields(log.Fields{
			"int_id":  intfid,
			"onu_id":  onuid,
			"eapolIn": eapolIn,
			"bytes":   bytes,
		}).Debug("EAPStart Sent")
		time.Sleep(30 * time.Second)
	}
	return nil
}

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: EapStart}

	eap := client.createEAPStart()
	bytes := client.createEAPOL(eap)
	resp := getEAPResponder()
	eapolIn := resp.eapolIn
	// start a loop that keeps sending EAPOL packets until it succeeds
	go sendEAPStart(intfid, onuid, client, bytes, eapolIn)
	// 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 == EapStart {
			reseap := c.createEAPResID()
			pkt := c.createEAPOL(reseap)
			logger.Debug("Moving from EapStart to EapRespid")
			return EapRespid, pkt, nil
		}
	} else if eap.Code == layers.EAPCodeRequest && eap.Type == layers.EAPTypeOTP {
		logger.Debug("Received EAP-Request/Challenge")
		logger.Debug(recvpkt.Dump())
		if cur == EapRespid {
			c.curID = eap.Id
			senddata := getMD5Data(c.curID, eap)
			senddata = append([]byte{0x10}, senddata...)
			sendeap := c.createEAPResCha(senddata)
			pkt := c.createEAPOL(sendeap)
			logger.Debug("Moving from EapRespid to EapRespcha")
			return EapRespcha, pkt, nil
		}
	} else if eap.Code == layers.EAPCodeSuccess && eap.Type == layers.EAPTypeNone {
		logger.Debug("Received EAP-Success")
		logger.Debug(recvpkt.Dump())
		if cur == EapRespcha {
			logger.Debug("Moving from EapRespcha to EapSuccess")
			return EapSuccess, 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
}
