#include "skype_proto.h"

void CSkypeProto::UpdateProfileAvatar(SEObject *obj, HANDLE hContact)
{
	uint newTS = obj->GetUintProp(/* *::P_AVATAR_TIMESTAMP */ 182);
	DWORD oldTS = this->GetSettingDword(hContact, "AvatarTS");
	
	wchar_t *path = this->GetContactAvatarFilePath(hContact);
	SEBinary data = obj->GetBinProp(/* *::P_AVATAR_IMAGE */ 37);

	if ((newTS > oldTS) || (!newTS && data.size() > 0 && _waccess(path, 0) == -1) || (newTS && _waccess(path, 0) == -1)) //hack for avatars without timestamp
	{
		FILE* fp = _wfopen(path, L"wb");
		if (fp)
		{
			fwrite(data.data(), sizeof(char), data.size(), fp);
			fclose(fp);

			this->SetSettingDword("AvatarTS", newTS);

			PROTO_AVATAR_INFORMATIONW pai = {0};
			pai.cbSize = sizeof(pai);
			pai.format = PA_FORMAT_JPEG;
			pai.hContact = hContact;
			wcscpy(pai.filename, path);
		
			this->SendBroadcast(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, (HANDLE)&pai, 0);
		}
	}

	delete path;
}

void CSkypeProto::UpdateProfileAboutText(SEObject *obj, HANDLE hContact)
{
	wchar_t* aboutText = ::mir_utf8decodeW(obj->GetStrProp(/* *::P_ABOUT */ 18));
	if ( !::wcslen(aboutText))
		this->DeleteSetting(hContact, "About");
	else
		this->SetSettingString(hContact, "About", aboutText);
	::mir_free(aboutText);
}

void CSkypeProto::UpdateProfileBirthday(SEObject *obj, HANDLE hContact)
{
	uint data = obj->GetUintProp(/* *::P_BIRTHDAY */ 7);
	if (data > 0)
	{
		TCHAR date[9];
		_itot_s(data, date, 10);

		INT day, month, year;
		_stscanf(date, _T("%04d%02d%02d"), &year, &month, &day);

		this->SetSettingByte(hContact, "BirthDay", day);
		this->SetSettingByte(hContact, "BirthMonth", month);
		this->SetSettingWord(hContact, "BirthYear", year);

		SYSTEMTIME sToday = {0};
		GetLocalTime(&sToday);
		int nAge = sToday.wYear - year;
		if (sToday.wMonth < month || (sToday.wMonth == month && sToday.wDay < day))
			nAge--;
		if (nAge)
			this->SetSettingWord( hContact, "Age", ( WORD )nAge );
	}
	else
	{
		this->DeleteSetting(hContact, "BirthDay");
		this->DeleteSetting(hContact, "BirthMonth");
		this->DeleteSetting(hContact, "BirthYear");
		this->DeleteSetting(hContact, "Age");
	}
}

void CSkypeProto::UpdateProfileCity(SEObject *obj, HANDLE hContact)
{
	wchar_t* city = ::mir_utf8decodeW(obj->GetStrProp(/* *::P_CITY */ 12));
	if ( !::wcslen(city))
		this->DeleteSetting(hContact, "City");
	else
		this->SetSettingString(hContact, "City", city);
	::mir_free(city);
}

void CSkypeProto::UpdateProfileCountry(SEObject *obj, HANDLE hContact)
{
	char* country;
	char* isocode = ::mir_strdup(obj->GetStrProp(/* *::P_COUNTRY */ 10));
	if ( !::strlen(isocode))
	{
		country = (char*)CallService(MS_UTILS_GETCOUNTRYBYNUMBER, 0xFFFF, 0);
		this->SetSettingString(hContact, "Country", ::mir_a2t(country));
	}
	else
	{
		country = (char*)CallService(MS_UTILS_GETCOUNTRYBYISOCODE, (WPARAM)isocode, 0);
		this->SetSettingString(hContact, "Country", ::mir_a2t(country));
	}
	::mir_free(isocode);
}

void CSkypeProto::UpdateProfileEmails(SEObject *obj, HANDLE hContact)
{
	wchar_t* emails = ::mir_a2u(obj->GetStrProp(/* *::P_EMAILS */ 16));
	if (wcscmp(emails, L"") == 0)
	{
		this->DeleteSetting(hContact, "e-mail0");
		this->DeleteSetting(hContact, "e-mail1");
		this->DeleteSetting(hContact, "e-mail2");
	}
	else
	{
		wchar_t* p = wcstok(emails, L" ");
		if (p == NULL)
		{
			this->SetSettingString(hContact, "e-mail0", emails);
		}
		else
		{
			this->SetSettingString(hContact, "e-mail0", p);
			p = wcstok(NULL, L" ");
			if (p) this->SetSettingString(hContact, "e-mail1", p);
			p = wcstok(NULL, L" ");
			if (p) this->SetSettingString(hContact, "e-mail2", p);
		}
		::mir_free(p);
	}
	::mir_free(emails);
}

void CSkypeProto::UpdateProfileFullName(SEObject *obj, HANDLE hContact)
{
	wchar_t* fullname = ::mir_utf8decodeW(obj->GetStrProp(/* *::P_FULLNAME */ 5));
	if ( !::wcslen(fullname))
		this->DeleteSetting(hContact, "LastName");
	else
		this->SetSettingString(hContact, "LastName", fullname);
	::mir_free(fullname);
}

void CSkypeProto::UpdateProfileGender(SEObject *obj, HANDLE hContact)
{
	uint data = obj->GetUintProp(/* *::P_GENDER */ 8);
	if (data)
		this->SetSettingByte(hContact, "Gender", (BYTE)(data == 1 ? 'M' : 'F'));
	else
		this->DeleteSetting(hContact, "Gender");
}

void CSkypeProto::UpdateProfileHomepage(SEObject *obj, HANDLE hContact)
{
	wchar_t* homepage = ::mir_a2u(obj->GetStrProp(/* *::P_HOMEPAGE */ 17));
	if (::wcscmp(homepage, L"") == 0)
		this->DeleteSetting(hContact, "Homepage");
	else
		this->SetSettingString(hContact, "Homepage", homepage);
	::mir_free(homepage);	
}

void CSkypeProto::UpdateProfileLanguages(SEObject *obj, HANDLE hContact)
{
	wchar_t *isocodes = ::mir_utf8decodeW(obj->GetStrProp(/* *::P_LANGUAGES */ 9));
	if ( !::wcslen(isocodes))
	{
		this->DeleteSetting(hContact, "Language1");
		this->DeleteSetting(hContact, "Language2");
		this->DeleteSetting(hContact, "Language3");
	}
	else
	{
		wchar_t* p = wcstok(isocodes, L" ");
		if (p == NULL)
		{
			this->SetSettingString(hContact, "e-Language1", isocodes);
		}
		else
		{
			this->SetSettingString(hContact, "e-Language1", p);
			p = wcstok(NULL, L" ");
			if (p) this->SetSettingString(hContact, "e-Language2", p);
			p = wcstok(NULL, L" ");
			if (p) this->SetSettingString(hContact, "e-Language3", p);
		}

		// todo: fix
		/*for (int i = 0; i < SIZEOF(CSkypeProto::languages); i++)
			if ( ::stricmp((char*)isocode, CSkypeProto::languages[i].ISOcode) == 0)
			{
				this->SetSettingString(hContact, "Language1", ::mir_a2u(CSkypeProto::languages[i].szName));
				break;
			}*/
	}
	::mir_free(isocodes);
}

void CSkypeProto::UpdateProfileMobilePhone(SEObject *obj, HANDLE hContact)
{
	wchar_t* phone = ::mir_a2u(obj->GetStrProp(/* *::P_PHONE_MOBILE */ 15));
	if ( !::wcslen(phone))
		this->DeleteSetting(hContact, "Cellular");
	else
		this->SetSettingString(hContact, "Cellular", phone);
	::mir_free(phone);
}

void CSkypeProto::UpdateProfilePhone(SEObject *obj, HANDLE hContact)
{
	wchar_t* phone = ::mir_a2u(obj->GetStrProp(/* *::P_PHONE_HOME */ 13));
	if ( !::wcslen(phone))
		this->DeleteSetting(hContact, "Phone");
	else
		this->SetSettingString(hContact, "Phone", phone);
	::mir_free(phone);
}

void CSkypeProto::UpdateProfileOfficePhone(SEObject *obj, HANDLE hContact)
{
	wchar_t* phone = ::mir_a2u(obj->GetStrProp(/* *::P_PHONE_OFFICE */ 14));
	if ( !::wcslen(phone))
		this->DeleteSetting(hContact, "CompanyPhone");
	else
		this->SetSettingString(hContact, "CompanyPhone", phone);		
	::mir_free(phone);
}

void CSkypeProto::UpdateProfileState(SEObject *obj, HANDLE hContact)
{
	wchar_t* state = ::mir_utf8decodeW(obj->GetStrProp(/* *::P_PROVINCE */ 11));
	if ( !::wcslen(state))
		this->DeleteSetting(hContact, "State");
	else
		this->SetSettingString(hContact, "State", state);		
	::mir_free(state);
}

void CSkypeProto::UpdateProfileStatusMessage(SEObject *obj, HANDLE hContact)
{
	wchar_t* statusMessage = ::mir_utf8decodeW(obj->GetStrProp(/* *::P_MOOD_TEXT */ 26));
	if ( !::wcslen(statusMessage))
		this->DeleteSetting(hContact, "XStatusMsg");
	else
		this->SetSettingString(hContact, "XStatusMsg", statusMessage);
	::mir_free(statusMessage);
}

void CSkypeProto::UpdateProfileTimezone(SEObject *obj, HANDLE hContact)
{
	uint data = obj->GetUintProp(/* *::P_TIMEZONE */ 27);
	if (data > 0)
	{
		uint diffmin = (data - 24*3600) / 60;
		wchar_t sign[2];
		if (diffmin < 0)
			::wcscpy(sign, L"-");
		else
			::wcscpy(sign, L"+");
		uint hours = ::abs((int)(diffmin / 60));
		uint mins = ::abs((int)(diffmin % 60));
		wchar_t timeshift[7];
		::mir_sntprintf(timeshift, SIZEOF(timeshift), _T("%s%d:%02d"), sign, hours, mins);
			
		wchar_t *szMin = wcschr(timeshift, ':');
		int nTz = ::_wtoi(timeshift) * -2;
		nTz += (nTz < 0 ? -1 : 1) * (szMin ? _ttoi( szMin + 1 ) / 30 : 0);

		TIME_ZONE_INFORMATION tzinfo;
		if (::GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT)
			nTz -= tzinfo.DaylightBias / 30;

		this->SetSettingByte(hContact, "Timezone", (signed char)nTz);
	}
	else
		this->DeleteSetting(hContact, "TimeZone");
}

void CSkypeProto::UpdateProfile(SEObject *obj, HANDLE hContact)
{
	uint newTS = obj->GetUintProp(/* *::P_PROFILE_TIMESTAMP */ 19);
	if (newTS > this->GetSettingDword("ProfileTS"))
	{
		this->UpdateProfileAboutText(obj, hContact);
		this->UpdateProfileBirthday(obj, hContact);
		this->UpdateProfileCity(obj, hContact);
		this->UpdateProfileCountry(obj, hContact);
		this->UpdateProfileEmails(obj, hContact);
		this->UpdateProfileFullName(obj, hContact);
		this->UpdateProfileGender(obj, hContact);
		this->UpdateProfileHomepage(obj, hContact);
		this->UpdateProfileLanguages(obj, hContact);
		this->UpdateProfileMobilePhone(obj, hContact);
		this->UpdateProfilePhone(obj, hContact);
		this->UpdateProfileOfficePhone(obj, hContact);
		this->UpdateProfileState(obj, hContact);
		this->UpdateProfileTimezone(obj, hContact);

		if (hContact)
		{
			this->UpdateContactOnlineSinceTime(obj, hContact);
			this->UpdateContactLastEventDate(obj, hContact);

			this->SetSettingString(hContact, "MirVer", L"Skype");
		}

		this->SetSettingDword("ProfileTS", newTS);
	}
}

void __cdecl CSkypeProto::LoadOwnInfo(void*)
{
	this->UpdateProfile(this->account.fetch());
}