/*
 * TILCLASS.CPP V1.3.3
 * Copyright (c) 2015-2018 Rudy Tellert Elektronik
 */

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <tchar.h>
#include "tilclass.h"

const Til::AnsiString &Til::AnsiString::operator = (TIL_PPROP prop)
{
	TIL_STRLEN len;

	clear();
	len = TIL_QUERY_STRLEN;
	TilGetStringA(prop, NULL, TIL_QUERY_STRLEN, &len);
	if (len != TIL_QUERY_STRLEN) {
		TIL_PSTR tmpStr = new TIL_CHAR[len + 1];
		if (tmpStr) {
			if (TilGetStringA(prop, tmpStr, len, NULL)) {
				tmpStr[len] = '\0';
				assign(tmpStr);
			}
			delete[] tmpStr;
		}
	}

	return *this;
}

const Til::String &Til::String::operator = (TIL_PPROP prop)
{
	TIL_STRLEN len;

	ansiString = prop;

	clear();
	len = TIL_QUERY_STRLEN;
	TilGetString(prop, NULL, TIL_QUERY_STRLEN, &len);
	if (len != TIL_QUERY_STRLEN) {
		TIL_PTSTR tmpStr = new TIL_TCHAR[len + 1];
		if (tmpStr) {
			if (TilGetString(prop, tmpStr, len, NULL)) {
				tmpStr[len] = TIL_T('\0');
				assign(tmpStr);
			}
			delete[] tmpStr;
		}
	}

	return *this;
}

Til::Timestamp::operator FILETIME() const
{
	FILETIME      ft;
	LARGE_INTEGER li;

	memset(&ft, '\0', sizeof(ft));
	if (time >= -109205 && time <= 10565994 && time != 0) {
		li.QuadPart = (LONGLONG)(time * 864000000000i64);
		li.QuadPart += 94353120000000005i64;
		ft.dwLowDateTime = li.LowPart;
		ft.dwHighDateTime = li.HighPart;
	}

	return ft;
}

Til::Timestamp::operator SYSTEMTIME() const
{
	SYSTEMTIME st;
	FILETIME   ft;
	
	memset(&st, '\0', sizeof(st));
	ft = *this;
	if (ft.dwHighDateTime != 0 || ft.dwLowDateTime != 0) {
		FileTimeToSystemTime(&ft, &st);
	}

	return st;
}

Til::Timestamp::operator TIL_DATETIME() const 
{
	TIL_DATETIME  dt;
	SYSTEMTIME    st;
	FILETIME      ft;
	LARGE_INTEGER li;

	memset(&dt, '\0', sizeof(dt));
	if (time >= -109205 && time <= 10565994 && time != 0) {
		li.QuadPart = (LONGLONG)(time * 864000000000i64);
		li.QuadPart += 94353120000000005i64;
		ft.dwLowDateTime = li.LowPart;
		ft.dwHighDateTime = li.HighPart;
		if (FileTimeToSystemTime(&ft, &st)) {
			dt.year = (TIL_UINT16)st.wYear;
			dt.month = (TIL_UINT16)st.wMonth;
			dt.day = (TIL_UINT16)st.wDay;
			dt.hour = (TIL_UINT16)st.wHour;
			dt.min = (TIL_UINT16)st.wMinute;
			dt.sec = (TIL_UINT16)st.wSecond;
			dt.usec = (TIL_UINT32)(li.QuadPart % 10000000) / 10;
		}
	}

	return dt;
}

Til::Timestamp::operator Til::String() const
{
	TIL_TCHAR buff[80];
	TIL_DATETIME dt = *this;
	String str;

	if (IsValid()) {
		_sntprintf(buff, 79, TIL_TEXT("%04u-%02u-%02u %02u:%02u:%02u.%06lu"),
			(unsigned)dt.year, (unsigned)dt.month, (unsigned)dt.day,
			(unsigned)dt.hour, (unsigned)dt.min, (unsigned)dt.sec,
			(unsigned long)dt.usec);
		buff[79] = TIL_T('\0');
		str.assign(buff);
	}

	return str;
}

void Til::Clear(void)
{
	if (obj) {
		TilDestroyObject(obj);
		obj = NULL;
	}
	fileName.clear();
	groups.clear();
	variables.clear();
	views.clear();
}

bool Til::Load(TIL_PCTSTR fileName)
{
	TIL_PPROP root, info, control, file, data, meas0, groups, views;
	size_t i;
	Groups::iterator gi;
	Views::iterator vi;

	Clear();
	std::basic_string<TIL_TCHAR> b;
	if (fileName) {
		b = fileName;
		Til::fileName.assign(fileName);
	}

	obj = TilCreateObject(TEMES_TIL_GUID);
	root = TilGetRootProperty(obj);
	info = TilGetProperty(root, tilInfo);
	GetValue(TilGetProperty(info, tilInfoVersion), &version);
	control = TilGetProperty(root, tilControl);
	file = TilGetProperty(control, tilControlFileName);
	if (!TilSetString(file, fileName)) {
		Clear();
		return false;
	}
	data = TilGetProperty(root, tilData);
	meas0 = TilGetVectorItem(TilGetProperty(data, tilDataMeas), 0);
	variables.Load(TilGetProperty(TilGetProperty(meas0, tilDataMeasComm), tilDataCommVariable));
	groups = TilGetProperty(meas0, tilDataMeasGroup);
	Til::groups.clear();
	Til::groups.resize(TilGetVectorSize(groups));
	for (i = 0, gi = Til::groups.begin(); gi != Til::groups.end(); i++, gi++) {
		gi->Load(TilGetVectorItem(groups, i));
	}
	views = TilGetProperty(data, tilDataView);
	Til::views.clear();
	Til::views.resize(TilGetVectorSize(views));
	for (i = 0, vi = Til::views.begin(); vi != Til::views.end(); i++, vi++) {
		vi->Load(TilGetVectorItem(views, i), Til::groups);
	}

	return true;
}

bool Til::Variables::Load(TIL_PPROP variables)
{
	size_t n = TilGetVectorSize(variables);

	for (size_t i = 0; i < n; i++) {
		TIL_PPROP variable, value;
		String key;
		variable = TilGetVectorItem(variables, i);
		key = TilGetProperty(variable, tilDataCommVariableKey);
		value = TilGetProperty(variable, tilDataCommVariableValue);
		switch (TilGetType(value)) {
			case TILID_STR:
			case TILID_WSTR: {
				String str;
				str = value;
				Variant val(str);
				(*this)[key] = val;
				break; }
			case TILID_FLOAT64:
			case TILID_FLOAT80: {
				double dbl;
				GetValue(value, &dbl);
				Variant val(dbl);
				(*this)[key] = val;
				break; }
		}
	}

	return true;
}

bool Til::Group::Load(TIL_PPROP group)
{
	TIL_PPROP prop;
	Signals::iterator si;
	size_t i;

	prop = TilGetProperty(group, tilDataMeasGroupComm);
	name = TilGetProperty(prop, tilDataMeasGroupCommName);
	comment = TilGetProperty(prop, tilDataMeasGroupCommComment);
	variables.Load(TilGetProperty(prop, tilDataMeasGroupCommVariable));
	GetValue(TilGetProperty(group, tilDataMeasGroupSampleCount), &sampleCount);
	GetValue(TilGetProperty(group, tilDataMeasGroupSampleRate), &sampleRate);
	time.Load(TilGetProperty(TilGetProperty(group, tilDataMeasGroupInfo), tilDataMeasGroupInfoTime));
	prop = TilGetProperty(group, tilDataMeasGroupSignal);
	signals.clear();
	signals.resize(TilGetVectorSize(prop));
	for (i = 0, si = signals.begin(); si != signals.end(); i++, si++) {
		si->Load(TilGetVectorItem(prop, i), this);
	}

	return true;
}

bool Til::Time::Load(TIL_PPROP time)
{
	TIL_PPROP prop;
	Sections::iterator si;
	size_t i;
	
	GetValue(TilGetProperty(time, tilDataMeasGroupInfoTimeHWSetup), &deviceSetup);
	GetValue(TilGetProperty(time, tilDataMeasGroupInfoTimeStart), &start);
	GetValue(TilGetProperty(time, tilDataMeasGroupInfoTimeHWReadOut), &deviceReadOut);
	prop = TilGetProperty(time, tilDataMeasGroupInfoTimeSection);
	sections.clear();
	sections.resize(TilGetVectorSize(prop));
	for (i = 0, si = sections.begin(); si != sections.end(); i++, si++) {
		si->Load(TilGetVectorItem(prop, i));
	}

	return true;
}

bool Til::Section::Load(TIL_PPROP section)
{
	GetValue(TilGetProperty(section, tilDataMeasGroupInfoTimeSectionSampleIndex), &sampleOffset);
	GetValue(TilGetProperty(section, tilDataMeasGroupInfoTimeSectionStart), &start);

	return true;
}

bool Til::Signal::Load(TIL_PPROP signal, Til::Group *group)
{
	TIL_PPROP prop, data;
	Markers::iterator mi;
	size_t i;

	prop = TilGetProperty(signal, tilDataMeasGroupSignalComm);
	name = TilGetProperty(prop, tilDataMeasGroupSignalCommName);
	comment = TilGetProperty(prop, tilDataMeasGroupSignalCommComment);
	variables.Load(TilGetProperty(prop, tilDataMeasGroupSignalCommVariable));
	unit = TilGetProperty(signal, tilDataMeasGroupSignalUnit);
	data = TilGetProperty(signal, tilDataMeasGroupSignalData);
	raw.Load(TilGetProperty(data, tilDataMeasGroupSignalDataRaw), group->sampleCount);
	attributes.Load(TilGetProperty(data, tilDataMeasGroupSignalDataFlags));
	viewDefaults.Load(TilGetProperty(signal, tilDataMeasGroupSignalView));
	iterator.Load(TilGetProperty(data, tilDataMeasGroupSignalDataIterator), dt_f64, group->sampleCount);
	Signal::group = group;
	prop = TilGetProperty(signal, tilDataMeasGroupSignalMarker);
	markers.clear();
	markers.resize(TilGetVectorSize(prop));
	for (i = 0, mi = markers.begin(); mi != markers.end(); i++, mi++) {
		mi->Load(TilGetVectorItem(prop, i));
	}
	return true;
}

bool Til::Raw::Load(TIL_PPROP raw, TIL_UINT64 sampleCount)
{
	GetValue(TilGetProperty(raw, tilDataMeasGroupSignalDataRawType), &dataType);
	GetValue(TilGetProperty(raw, tilDataMeasGroupSignalDataRawFactor), &factor, 1);
	GetValue(TilGetProperty(raw, tilDataMeasGroupSignalDataRawOffset), &offset);
	storage.Load(TilGetProperty(raw, tilDataMeasGroupSignalDataRawFile));
	iterator.Load(TilGetProperty(raw, tilDataMeasGroupSignalDataRawIterator), dataType, sampleCount);
	
	return true;
}

bool Til::Storage::Load(TIL_PPROP storage)
{
	fileName = TilGetProperty(storage, tilDataMeasGroupSignalDataRawFileName);
	GetValue(TilGetProperty(storage, tilDataMeasGroupSignalDataRawFileOffset), &offset);
	GetValue(TilGetProperty(storage, tilDataMeasGroupSignalDataRawFileDataSize), &dataSize);
	GetValue(TilGetProperty(storage, tilDataMeasGroupSignalDataRawFileGap), &gap);

	return true;
}

bool Til::Iterator::Load(TIL_PPROP prop, unsigned dataType, TIL_UINT64 itemCount)
{
	Iterator::dataType = dataType;
	Iterator::itemCount = itemCount;
	itemSize = TilGetIteratorItemSize(prop);
	iterator = prop;

	return true;
}

bool Til::Attributes::Load(TIL_PPROP attributes)
{
	GetValue(TilGetProperty(attributes, tilDataMeasGroupSignalDataFlagsQuantized), &quantized);
	return true;
}

bool Til::ViewDefaults::Load(TIL_PPROP viewDefaults)
{
	GetValue(TilGetProperty(viewDefaults, tilDataMeasGroupSignalViewMin), &min);
	GetValue(TilGetProperty(viewDefaults, tilDataMeasGroupSignalViewMax), &max);

	return true;
}

bool Til::Marker::Load(TIL_PPROP marker)
{
	name = TilGetProperty(marker, tilDataMeasGroupSignalMarkerName);
	GetValue(TilGetProperty(marker, tilDataMeasGroupSignalMarkerSampleIndex), &sampleIndex, -1);
	GetValue(TilGetProperty(marker, tilDataMeasGroupSignalMarkerVisible), &visibleAttribute);
	GetValue(TilGetProperty(marker, tilDataMeasGroupSignalMarkerType), &type);
	text = TilGetProperty(marker, tilDataMeasGroupSignalMarkerText);
	GetValue(TilGetProperty(marker, tilDataMeasGroupSignalMarkerTextAngle), &textAngle, -1);
	GetValue(TilGetProperty(marker, tilDataMeasGroupSignalMarkerTextDistance), &textDistance, -1);

	return true;
}

bool Til::View::Load(TIL_PPROP view, const Groups &groups)
{
	TIL_PPROP items;
	ViewItems::iterator vi;
	size_t i;

	name = TilGetProperty(TilGetProperty(view, tilDataViewComm), tilDataViewCommName);
	items = TilGetProperty(view, tilDataViewItem);
	viewItems.clear();
	viewItems.resize(TilGetVectorSize(items));
	for (i = 0, vi = viewItems.begin(); vi != viewItems.end(); i++, vi++) {
		vi->Load(TilGetVectorItem(items, i), groups);
	}
	
	return true;
}

bool Til::ViewItem::Load(TIL_PPROP viewItem, const Groups &groups)
{
	info.Load(TilGetProperty(viewItem, tilDataViewItemSignalInfo), groups);
	name = TilGetProperty(TilGetProperty(viewItem, tilDataViewItemComm), tilDataViewItemCommName);
	unit = TilGetProperty(viewItem, tilDataViewItemUnit);
	GetValue(TilGetProperty(viewItem, tilDataViewItemFactor), &factor, 1);
	GetValue(TilGetProperty(viewItem, tilDataViewItemOffset), &offset);
	GetValue(TilGetProperty(viewItem, tilDataViewItemRefFactor), &refFactor, 1);
	GetValue(TilGetProperty(viewItem, tilDataViewItemRefOffset), &refOffset);
	GetValue(TilGetProperty(viewItem, tilDataViewItemSlotVisible), &slotVisibleAttribute);
	GetValue(TilGetProperty(viewItem, tilDataViewItemDigits), &digits);
	GetValue(TilGetProperty(viewItem, tilDataViewItemCurveVisible), &curveVisibleAttribute);
	GetValue(TilGetProperty(viewItem, tilDataViewItemColor), &curveColor);
	GetValue(TilGetProperty(viewItem, tilDataViewItemThickness), &curveThickness);
	GetValue(TilGetProperty(viewItem, tilDataViewItemPattern), &curveLinePattern);
	GetValue(TilGetProperty(viewItem, tilDataViewItemBegin), &begin);
	GetValue(TilGetProperty(viewItem, tilDataViewItemEnd), &end);
	GetValue(TilGetProperty(viewItem, tilDataViewItemAxisPos), &axisPosition);
	GetValue(TilGetProperty(viewItem, tilDataViewItemXAxisPos), &xAxisPosition);
	GetValue(TilGetProperty(viewItem, tilDataViewItemAxisMin), &axisMin);
	GetValue(TilGetProperty(viewItem, tilDataViewItemAxisMax), &axisMax);
	axisName = TilGetProperty(viewItem, tilDataViewItemAxisName);
	axisTitle = TilGetProperty(viewItem, tilDataViewItemAxisTitle);
	GetValue(TilGetProperty(viewItem, tilDataViewItemAxisDefMin), &axisDefaultMin);
	GetValue(TilGetProperty(viewItem, tilDataViewItemAxisDefMax), &axisDefaultMax);

	return true;
}

bool Til::SignalInfo::Load(TIL_PPROP signalInfo, const Groups &groups)
{
	GetValue(TilGetProperty(signalInfo, tilDataViewItemSignalInfoMeasIndex), &measIndex);
	GetValue(TilGetProperty(signalInfo, tilDataViewItemSignalInfoGroupIndex), &groupIndex);
	GetValue(TilGetProperty(signalInfo, tilDataViewItemSignalInfoSignalIndex), &signalIndex);
	if (measIndex == 0 && groups.size() > groupIndex) {
		if (groups[groupIndex].signals.size() > 0) refSignal = &groups[groupIndex].signals[0];
		if (groups[groupIndex].signals.size() > signalIndex) signal = &groups[groupIndex].signals[signalIndex];
	}

	return true;
}
