using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using bbiwarg.Recognition.TouchRecognition;
using bbiwarg.Utility;
using bbiwarg.Input.InputHandling;
using TUIO;

namespace bbiwarg.TUIO
{
    class TuioCommunicator
    {
        private TuioServer server;
        private Dictionary<int, TuioCursor> cursors;

        public TuioCommunicator(string host, int port)
        {
            server = new TuioServer(host, port);
            cursors = new Dictionary<int, TuioCursor>();
        }

        public void handleNewFrameData(InputHandler sender, EventArgs e)
        {
            server.initFrame();
            FrameData frameData = sender.FrameData;
            lock (frameData) {
                foreach (TouchEventArgs te in frameData.TouchEvents) {
                    switch (te.Type) {
                        case TouchEventType.Down:
                            TuioCursor cursor = server.addTuioCursor(te.Touch.RelativePosition.X, te.Touch.RelativePosition.Y);
                            cursors.Add(te.TrackID, cursor);
                            break;
                        case TouchEventType.Move:
                            server.updateTuioCursor(cursors[te.TrackID], te.Touch.RelativePosition.X, te.Touch.RelativePosition.Y);
                            break;
                        case TouchEventType.Up:
                            server.removeTuioCursor(cursors[te.TrackID]);
                            cursors.Remove(te.TrackID);
                            break;
                    }
                }
            }

            server.commitFrame();
        }

        public void close()
        {
            server.close();
        }

        public void reset()
        {
            foreach (int id in cursors.Keys)
            {
                server.removeTuioCursor(cursors[id]);
            }
            cursors.Clear();
        }

        public static bool tryParseIPAddress(String ipString, out IPAddress ipAddress) {
            return (IPAddress.TryParse(ipString, out ipAddress) && ipAddress.AddressFamily == AddressFamily.InterNetwork);
        }

        public static bool tryParsePort(String portString, out Int16 port) {
            return Int16.TryParse(portString, out port);
        }
    }
}
