#include "UnityPrefix.h"
#include "Configuration/UnityConfigureOther.h"
#include "Runtime/Utilities/Argv.h"
#include "Editor/Src/Utility/Base64.h"
#include "Runtime/Utilities/HashFunctions.h"
#include "Editor/Src/Application.h"
#include "Editor/Src/LicenseInfo.h"
#include "Editor/Src/LicenseManager.h"
#include "Editor/Platform/Interface/EditorUtility.h"

#include <string.h>
#if UNITY_OSX
#include <arpa/inet.h>
#endif
#if UNITY_WIN
#include <WinSock.h>
#include "PlatformDependent/Win/WinUnicode.h"
#pragma warning(disable:4200)
#endif

#define DEBUG_COPY_PROTECTION 0


LicenseManager* m_LicenseManager = NULL;

LicenseInfo* gSingleton = NULL;

LicenseInfo::LicenseInfo() : 
	m_DidCreateWindow(false)
	, m_UserClosedWindow(false)
	, m_ServerErrorSignaled(false)
	, m_ShouldExitOnCancel(false)
	, m_RunningUserTriggeredUpdate(false)
#if UNITY_WIN
	, m_RunningUserReactivation(false)
#endif
{
	InitializeProtection();
}


void LicenseInfo::InitializeProtection() 
{
//	m_TX_RX_IDS.clear();
//	if (m_LicenseManager == NULL)
//		m_LicenseManager = new LicenseManager();
//	int state = m_LicenseManager->Initialize();
//	switch(state)
//	{
//		case kLicenseStatus_Valid:
//			break;
//
//		case kLicenseStatus_Unknown:
//			break;
//		
//		// No PACE or ULF license found
//		case kLicenseErrorFlag_NoLicense:
//			break;
//
//		case kLicenseErrorFlag_PaceLicenseExpired:
//			GenericErrorDialog("Your license has expired.");
//			break;
//
//		case kLicenseErrorFlag_FileCompromised:
//			GenericErrorDialog("Unity license information is invalid.");
//			break;
//
//		case kLicenseErrorFlag_LicenseNotReadyForUse:
//			GenericErrorDialog("Unity license is not yet valid.");
//			break;
//
//		case kLicenseErrorFlag_LicenseExpired:
//			GenericErrorDialog("Unity license has expired.");
//			break;
//		
//		case kLicenseErrorFlag_Initialization:
//			if (DisplayDialog("Error initializing license system.", "Please contact support@unity3d.com\n\n", "Report a bug", "Quit"))
//				LaunchBugReporter(kManualSimple);
//			exit(1);
//			break;
//			
//		case kLicenseErrorFlag_VersionMismatch:
//			GenericErrorDialog("License is not for this version of Unity.");
//			break;
//
//		case kLicenseErrorFlag_MachineBinding1:
//#if UNITY_WIN
//			// If only Product ID changed we'll allow the user to deactivate the license and reactivate.
//			if (DisplayDialog("License issue detected!", "There was a problem validating the license because the Operating System identification seems to have changed.\n\n Would you like to deactivate this license and re-activate?\n\n For more information see online help at\nhttp://unity3d.com/unity/err/license\nFor assistance contact support@unity3d.com", "Quit", "Re-activate"))
//				exit(1);
//			else
//			{
//				m_RunningUserReactivation = true;
//				DisplayProgressbar("Re-activating", "Returning current license...", 0);
//				m_LicenseManager->ReturnLicense();
//			}
//			break;
//#endif
//		case kLicenseErrorFlag_MachineBinding2:
//		case kLicenseErrorFlag_MachineBinding4:
//			GenericErrorDialog("Machine identification is invalid for current license.");
//			break;
//
//		default:
//			UnknownErrorDialog (Format("An unknown error has occurred (0x%x).", state).c_str());
//			break;
//	}
	
	gSingleton = this;
	m_Tokens = 1;
	
	/*m_Tokens = m_LicenseManager->GetTokens();
	if (GetApplicationPtr())
		GetApplicationPtr()->ReadLicenseInfo();*/
}

void LicenseInfo::SetRXValue(const char* value)
{
	// m_TX_RX_IDS = m_LicenseManager->m_txID + ";" + value;
}

void LicenseInfo::SignalUserClosedWindow()
{
	m_UserClosedWindow = true;
}


void LicenseInfo::GenericErrorDialog(const char* title)
{
	DisplayErrorDialog(title, "http://unity3d.com/unity/err/license");
}

void LicenseInfo::UnknownErrorDialog(const char* title)
{
	DisplayErrorDialog(title, "http://unity3d.com/unity/err/unknown");
}

void LicenseInfo::DisplayErrorDialog(const char* title, const char* url)
{
	if (DisplayDialog(title, Format("For more information see online help at\n%s\n\nFor assistance contact support@unity3d.com", url), "Quit", "Re-activate"))
	{
		exit(1);
	}
	else
	{
		m_ShouldExitOnCancel = true;
		NewActivation();
	}
}

// Flush editor UI state and repaint for when switching licensing
void LicenseInfo::ReloadEditorUI ()
{
	// When launching directly into the license system message pump (no license existed before) then this pointer can be null
	if (GetApplicationPtr ())
	{
		GetApplicationPtr ()->RequestScriptReload ();
		GetApplicationPtr ()->RequestRepaintAllViews ();
	}
}

// This method is called from the main loop - void Application::TickTimer()
void LicenseInfo::Tick() 
{
	// No license found? or do we need to update an existing license?
	
}

void LicenseInfo::ShowUpdateFeedbackDialog(bool success)
{
	
}


bool LicenseInfo::GetLargeFlag(LicenseInfoFlag f)
{
	return true;
}


string LicenseInfo::GetLicenseString ()
{
	return "";
}

bool LicenseInfo::OngoingServerCommunication()
{
	if( m_LicenseManager->m_State == kOngoingLicenseServerCommunication || m_LicenseManager->m_State == kOngoingActivationServerCommunication )
	{
		return true;
	}
	else
	{
		return false;
	}
}

string LicenseInfo::GetMachineID()
{
	return m_LicenseManager->GetMachineID();	
}

string LicenseInfo::GetAuthToken ()
{
	return m_LicenseManager->GetAuthToken(); 
}


// Warning, m_Tokens is only updated in InitializeProtection, if the LicenseManager has updated
// it's m_Tokens after a server update InitializeProtection must be called
UInt64 LicenseInfo::GetRawFlags ()
{
	return m_Tokens;
}


void LicenseInfo::Reauthorize()
{
	CallStaticMonoMethod("LicenseManagementWindow", "ShowWindow");
}


LicenseInfo::~LicenseInfo()
{
	if (gSingleton == this)
		gSingleton = NULL;
	
	delete m_LicenseManager;
}


LicenseInfo* LicenseInfo::Get ()
{
	if(gSingleton == NULL)
		gSingleton = new LicenseInfo();
	return gSingleton;
}

void LicenseInfo::Cleanup ()
{
	delete gSingleton;
	gSingleton = NULL;
}


string LicenseInfo::GetDisplaySerialNumber ()
{
	return "";
}


int LicenseInfo::SaveLicenseFile ( string licenseData )
{
	return 1;// m_LicenseManager->WriteLicenseFile( licenseData, true );
}


void LicenseInfo::ReturnLicense ()
{
	/*if( DisplayDialog ("Information", "Are you sure you want to return your license?", "Yes", "No") )
	{
		m_LicenseManager->ReturnLicense();
	}*/

}


bool LicenseInfo::IsLicenseUpdated ()
{
	return m_LicenseManager->IsLicenseUpdated();
}


void LicenseInfo::CallActivationServer ()
{
	m_LicenseManager->CallActivationServer();
}

void LicenseInfo::CallActivationServer (string TX_RX_IDS)
{
	m_LicenseManager->CallActivationServer(TX_RX_IDS);
}


void LicenseInfo::QueryLicenseUpdate (bool forceCheck)
{
	if( (m_LicenseManager->m_LicenseStatus == kLicenseStatus_Valid && m_LicenseManager->m_MustUpdate) || forceCheck )
	{
		 if (forceCheck)
			gSingleton->m_RunningUserTriggeredUpdate = true;
		m_LicenseManager->QueryLicenseUpdate();
	}
}


void LicenseInfo::SignalServerError()
{
	m_ServerErrorSignaled = true;
}

void LicenseInfo::NewActivation ()
{
	m_TX_RX_IDS.clear();
	m_LicenseManager->NewActivation();
}

void LicenseInfo::ManualActivation ()
{
	m_LicenseManager->ManualActivation();
}

const std::string LicenseInfo::GetLicenseURL()
{
	return m_LicenseManager->GetLicenseURL();
}

bool LicenseInfo::UnknownStatus()
{
	return m_LicenseManager->UnknownStatus();
}

void LicenseLog (const char* format, ...)
{
	#if DEBUG_COPY_PROTECTION
	time_t getTime = time(NULL);
	struct tm *now = localtime(&getTime);
	va_list va;
	va_start( va, format );
	printf_console("\nLICENSE SYSTEM [%d%d%d %d:%d:%d] %s\n", now->tm_year+1900, now->tm_mon+1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec, VFormat(format, va).c_str());
	#endif
}
