module Nettle.LLDP.LLDP (

             LLDPDU ( .. ), 
             getLLDPInEthernet

                        ) where

import Data.Binary
import Data.Binary.Get (skip)
import Nettle.Ethernet.EthernetAddress
import Nettle.Ethernet.EthernetFrame
import Control.Monad.Error

data LLDPDU = LLDPDU {
      
      chassisID  :: Word64,
      -- make PortID of type PortID (=Word16) when that definition is refactored
      -- from Nettle.OpenFlow.Messages0x98 to Nettle.OpenFlow.Base
      portID     :: Word16,
      timeToLive :: Word16

    } deriving (Eq, Show)


instance Binary LLDPDU where
    get = do

      skip $ headerLength + subtypeLength
      address <- get

      skip $ headerLength + subtypeLength
      portNumber <- get

      skip $ headerLength
      timeUntilExpiration <- get
      
      skip headerLength

      return LLDPDU { 
                   chassisID=address, 
                   portID=portNumber, 
                   timeToLive=timeUntilExpiration 
                 }


    put LLDPDU { chassisID=cid, portID=pid, timeToLive=ttl } = do
                         
                         put chassisIDHeader
                         put chassisIDSubtype
                         put cid

                         put portIDHeader
                         put portIDSubtype
                         put pid

                         put timeToLiveHeader
                         put ttl

                         put endOfLLDPDUTLV

chassisIDHeader = 521 :: Word16
chassisIDSubtype = 4 :: Word8
portIDHeader = 1027 :: Word16
portIDSubtype = 2 :: Word8
timeToLiveHeader = 1538 :: Word16
endOfLLDPDUTLV = 0 :: Word16

headerLength = 2
subtypeLength = 1

getLLDPInEthernet :: GetE LLDPDU
getLLDPInEthernet = 
    do ethHeader <- getEthHeader
       lldpdu    <- lift get
       return lldpdu