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

public class GameErrorLogger : MonoBehaviour {

	public bool logError = false;
	public bool logException = false;
	static string path;

	static Dictionary<string, float> sent;

	// Use this for initialization
	void Awake() {
		path = Path.Combine(Environment.CurrentDirectory, "log.txt");
		sent = new Dictionary<string, float>();
	}

	void OnEnable() {
		Application.logMessageReceivedThreaded += HandleLog;
	}
	void OnDisable() {
		Application.logMessageReceivedThreaded -= HandleLog;
	}

	void OnApplicationQuit() {
		// since this isn't shared we can add a little appendage to the end to break it up a bit between plays
		#if UNITY_EDITOR || UNITY_STANDALONE_OSX || UNITY_STANDALONE_WIN
		LogEndOfExcution();
		#endif
	}

	// Update is called once per frame
	void Update() {
		// can only be used in the editor to force a quick log for testing
		if (logError) {
			Debug.LogError("testing log error handling");
			logError = false;
		}
		if (logException) {
			Debug.LogException(new Exception("testing exception handling"));
			logException = false;
		}
	}

	void HandleLog(string logString, string stackTrace, LogType type) {
		if (type == LogType.Error || type == LogType.Exception) {
			LogEverywhereICan(logString, stackTrace);
		}
	}

	// use this if we want to track something manually
	public static void WriteToLog(string message) {
		LogEverywhereICan(message, UnityEngine.StackTraceUtility.ExtractStackTrace());
		print(message); // print so you can see it in the editor console as well
	}

	static void LogEverywhereICan(string logString, string stackTrace) {
		#if UNITY_EDITOR || UNITY_STANDALONE_OSX || UNITY_STANDALONE_WIN
		LogToFileOnSystem(logString, stackTrace);
		#endif
		//if (PersistentData.localPlayerData.playFabId == null)
		//    return;

		//// send it to server through cloudscript
		//string completeMessage = "ID: " + PersistentData.localPlayerData.playFabId + "\n"
		//    + "UTC: " + DateTime.UtcNow + "\n"
		//    + logString + "\n"
		//    + stackTrace + "\n";

		//if (CanISendToServer(stackTrace)) {
		//    PlayfabCloudScriptAPI.LogErrorToServer(completeMessage);
		//    sent.Add(stackTrace, Time.unscaledTime + 5.0f);
		//}
	}

	static bool CanISendToServer(string stackTrace) {
		bool canSend = true;
		RemoveOldSends();
		foreach (KeyValuePair<string, float> entry in sent) {
			if (entry.Key == stackTrace) {
				return canSend = false;
			}
		}
		return canSend;
	}

	static void RemoveOldSends() {
		List<string> entriesToRemove = new List<string>();
		foreach (KeyValuePair<string, float> entry in sent) {
			if (entry.Value < Time.unscaledTime) {
				entriesToRemove.Add(entry.Key);
			}
		}

		for (int i = 0; i < entriesToRemove.Count; i++) {
			sent.Remove(entriesToRemove[i]);
		}
	}

	static void LogToFileOnSystem(string message, string stackTrace) {
		// This text is added only once to the file.
		if (!File.Exists(path)) {
			// Create a file to write to.
			using (StreamWriter sw = File.CreateText(path)) {
				sw.WriteLine("Welcome to the error log!");
				sw.WriteLine("");
			}
		}

		using (StreamWriter sw = File.AppendText(path)) {
			//if (PersistentData.localPlayerData.playFabId != null) {
			//    sw.WriteLine("ID: " + PersistentData.localPlayerData.playFabId);
			//}
			sw.WriteLine("UTC: " + DateTime.UtcNow);
			sw.WriteLine(message);
			sw.WriteLine(stackTrace);
			sw.WriteLine();
		}
	}

	// should only be called in standalone and editor
	void LogEndOfExcution() {
		using (StreamWriter sw = File.AppendText(path)) {
			sw.WriteLine("////////////////");
			sw.WriteLine("END OF EXECUTION");
			sw.WriteLine("////////////////");
			sw.WriteLine("");
		}
	}
}
