using System;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using OpenDis.Core;
using OpenDis.Dis1998;
using OpenDis.Enumerations;
using UnityEngine.UI;

public class Receiver : MonoBehaviour {

    UdpClient client;
    IPEndPoint localEp;
    EntityStatePdu newEntityStatePDU;
    IPAddress multicastaddress;
    PduProcessor pduProcessor;
    int PDU_TYPE_POSITION = 2;
    public GameObject locationText;
    Vector3Double location;
    EntityID entityID;
    EntityType entityType;

    // Use this for initialization
    public void onClick () {

        Debug.Log("Start receiving...");

        // Create UDP Client to receive data
        client = new UdpClient();
        client.ExclusiveAddressUse = false;
        localEp = new IPEndPoint(IPAddress.Any, 3000);
        client.Client.SetSocketOption(SocketOptionLevel.Socket, 
            SocketOptionName.ReuseAddress, true);
        client.ExclusiveAddressUse = false;
        client.Client.Bind(localEp);
        multicastaddress = IPAddress.Parse("239.1.2.3");
        client.JoinMulticastGroup(multicastaddress);
        locationText = GameObject.FindGameObjectWithTag("ReceiverLocationText");

        // Broadcast IP - Client
        InvokeRepeating("BroadcastClientIP", 0, 1f);
    }

    // Receive data
    void BroadcastClientIP()
    {
        try
        {
            if(client.Available > 0)
            {
                // Blocks until a message returns on this socket from a remote host.
                Byte[] receivedBytes = client.Receive(ref localEp);

                if(receivedBytes != null && receivedBytes.Length > 0)
                {
                    try
                    {
                        PduType pduType = (PduType)receivedBytes[PDU_TYPE_POSITION];
                        Pdu pdu = PduProcessor.UnmarshalRawPdu(pduType, receivedBytes, Endian.Big);
                        switch ((PduType)pdu.PduType)
                        {
                            case PduType.EntityState:
                                ProcessEntityStatePdu((EntityStatePdu)pdu);
                                SetLocationText();
                                break;
                            default:
                                break;
                        }
                    } catch (Exception e)
                    {
                        Debug.LogError(e.ToString());
                    }
                }
            }
        }
        catch (Exception e)
        {
            Debug.LogError(e.ToString());
        }
    }

    // Process Entity State PDU
    void ProcessEntityStatePdu(EntityStatePdu espdu)
    {
        entityID = espdu.EntityID;
        entityType = espdu.EntityType;
        location = espdu.EntityLocation;
    }

    // Print NavySeal info on screen
    void SetLocationText()
    {
        if (entityID.Entity != 1)
        {
            locationText.GetComponent<Text>().text = String.Format("NAVY SEAL RECEIVER\nID: {0}\nCountry: {1}\nCategory: {2}\nLocation: ({3}, {4}, {5})", entityID.Entity.ToString(), entityType.Country.ToString(), entityType.Category.ToString(), location.X.ToString("F2"), location.Y.ToString("F2"), location.Z.ToString("F2"));
            Debug.Log(String.Format("NAVY SEAL RECEIVER\nID: {0}\nCountry: {1}\nCategory: {2}\nLocation: ({3}, {4}, {5})", entityID.Entity.ToString(), entityType.Country.ToString(), entityType.Category.ToString(), location.X.ToString("F2"), location.Y.ToString("F2"), location.Z.ToString("F2")));
        }
    }

}