﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using Nanolink;
using NanoBuffers;

namespace NanolinkDemo {
	public class MySerialize {
		private const byte CMD_MOVE = 1;

		public static byte[] toBytes(Hashtable values) {
			NanoWriter nanoWriter = new NanoWriter ();

			string name = (string) values["name"];
			switch(name) {
			case "move":
				nanoWriter.putInt (CMD_MOVE).put ((Vector3)values ["target"], 3);
				break;

			default:
				Debug.Log ("MySerialize::toBytes 未支持的命令: " + name);
				break;
			}

			return nanoWriter.getBytes ();
		}

		public static Hashtable fromBytes(byte[] buf) {
			NanoReader nanoReader = new NanoReader (buf);

			Hashtable values = new Hashtable ();

			byte cmd;
			nanoReader.getInt (out cmd);

			switch(cmd) {
			case CMD_MOVE:
				Vector3 target;
				nanoReader.get (out target, 3);

				values.Add ("name", "move");
				values.Add ("target", target);

				break;

			default:
				Debug.Log ("MySerialize::fromBytes 未支持的命令: " + cmd);
				break;
			}

			return values;
		}
	}

	public class MyClient : NanoClient {
		protected override void onMessage (byte[] data, byte fromIndex) {
			Hashtable values = MySerialize.fromBytes (data);

			string name = (string) values["name"];

			switch(name) {
			case "move":
				{
					GameObject player = GameObject.Find ("Player-" + fromIndex);
					if (player != null) {
						MyPlayer controller = player.GetComponent<MyPlayer> ();
						controller.onEvent (values);
					}
				}
				break;
			}
		}

		protected override void onResync(byte fromIndex) {
			// 匹配成功时，同步玩家数据（如：昵称，位置，皮肤，...）给其他玩家

			// 发送当前玩家位置
			GameObject player = GameObject.Find("Player-" + getInt ("client-index"));
			if(player != null) {
				MyPlayer controller = player.GetComponent<MyPlayer> ();
				controller.moveEvent ();
			}
		}

		protected override void onStatusChanged(string newStatus, string oldStatus) {
			Debug.Log ("状态由 " + oldStatus + " 改为 " + newStatus);
		}

		protected override void onConnected() {
		}

		protected override void onDisconnected(int error) {
			if (error == 0) {
				if (disconnectedBySelf)
					Debug.Log ("主动断开");
				else
					Debug.Log ("对方断开");
			} else {
				// 错误代码具体参考 "Nanolink SDK 接口说明" 中 lastError 定义
				if (error == 501) {
					if (getInt ("last-time", -2) < 2000)
						Debug.Log ("超时断开, 可能是对方原因");
					else
						Debug.Log ("超时断开, 可能是己方原因");
				}
			}
		}

		protected override void onPlayer(byte clientIndex, string e) {
			// Debug.Log ("onPlayer, clientIndex: " + clientIndex + "; e: " + e);
		}

		// 输出调试信息，方便调试和查看当前状态信息
		// 不需要时，删除 drawGUI 即可
		public void drawGUI () {
			// 回放不支持 stats 数据, 忽略
			if (getInt ("mode") == 0)
				return;

			GUIStyle guiStyle = new GUIStyle ();
			guiStyle.normal.textColor = Color.white;
			guiStyle.fontSize = 32;

			// 延迟 us->ms
			float latency = getInt ("latency") / 1000.0f;

			// 当前的状态
			string s = getStatus();
			if (s == "connected") {
				if (getInt ("is-master") == 1)
					s += ", 主场";
				else
					s += ", 客场";
			}

			// 对方 ID (或房间号)
			string targetId = getString("target-id");
			if (targetId.Length > 8)
				targetId = targetId.Substring (targetId.Length - 8);

			// 当前玩家 ID
			string clientId = getString("client-id");
			if (clientId.Length > 8)
				clientId = clientId.Substring (clientId.Length - 8);

			// Stats 数据
			string stats = getString("stats");

			// Stats 数据映射字典
			Dictionary<string, string> dictionary = new Dictionary<string, string>();

			string[] strs = stats.Split('\n');
			foreach (var str in strs) {
				string[] keyValue = str.Split('=');
				if (keyValue.Length > 1) {
					dictionary.Add(keyValue[0], keyValue[1]);
				}
			}

			string targetIdStr = "";

			// 当前在线人数
			string thePlayers = "";

			// 发送接收数据明细
			string sendData = "";
			string recvData = "";
			sendData = "发送:  " + dictionary ["send.task.index"] + "次/ " + dictionary ["send.task.bytes"] + "字节/ " + dictionary ["send.total.bytes"] + "字节";

			// 根据连接模式区分输出信息
			if(getInt ("mode") == 3) {
				targetIdStr = "房间: " + targetId;

				thePlayers = ", 当前人数: " + getInt ("players", 5000);
			} else {
				targetIdStr = "对方: " + targetId;

				// 1 VS 1 延迟／2
				latency = latency / 2;

				recvData = ", 接收: " + dictionary ["recv.task.index"] + "次/ " + dictionary ["recv.task.bytes"] + "字节/ " + dictionary ["recv.total.bytes"] + "字节";
			}

			GUI.Label (new Rect(40, 140, 200, 200), "状态: " + s + thePlayers, guiStyle);

			GUI.Label (new Rect(40, 180, 200, 200), targetIdStr + ", 设备: " + clientId, guiStyle);

			// 延迟
			if (latency >= 0)
				GUI.Label (new Rect(40, 220, 200, 200), "时延: " + latency + " ms", guiStyle);
			else
				GUI.Label (new Rect(40, 220, 200, 200), "时延: ", guiStyle);

			GUI.Label (new Rect (40, 260, 200, 200), sendData + recvData, guiStyle);

		}
	}
}
