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

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

LPTSTR GetDataTypeText(unsigned dataType, TIL_UINT64 sampleCount);

int _tmain(int argc, _TCHAR* argv[])
{
	Til til;
	size_t g, s, k, sampleCount;
	
	if (argc < 2) {
		_putts(_T("VIEW_TMS V1.3.3 - Copyright (c) 2015-2018 Rudy Tellert Elektronik\n")
			   _T("SYNTAX: VIEW_TMS filename.tms"));
		return 87;
	}

	if (!til.Load(argv[1])) {
		_tprintf(_T("Cannot open \"%s\"!\n"), argv[1]);
		return 1;
	}
	for (g = 0; g < til.groups.size(); g++) {
		Til::Group &group = til.groups[g];
		_tprintf(_T("\nGroup %I64u/%I64u:\n"), (TIL_UINT64)g + 1, (TIL_UINT64)til.groups.size());
		_tprintf(_T("  SampleCount = %I64u\n"), group.sampleCount);
		_tprintf(_T("  SampleRate = %lg s\n"), group.sampleRate);
		if (group.time.deviceSetup.IsValid()) {
			_tprintf(_T("  HWSetup = %s\n"), ((Til::String)group.time.deviceSetup).c_str());
		}
		if (group.time.start.IsValid()) {
			_tprintf(_T("  Start = %s\n"), ((Til::String)group.time.start).c_str());
		}
		if (group.time.deviceReadOut.IsValid()) {
			_tprintf(_T("  HWReadOut = %s\n"), ((Til::String)group.time.deviceReadOut).c_str());
		}
		for (s = 0; s < group.time.sections.size(); s++) {
			Til::Section &section = group.time.sections[s];
			TIL_UINT64 lastSampleIndex;
			if (s + 1 < group.time.sections.size()) {
				lastSampleIndex = group.time.sections[s + 1].sampleOffset;
			}
			else {
				lastSampleIndex = group.sampleCount;
			}
			if (lastSampleIndex) lastSampleIndex--;
			_tprintf(_T("  Sample range of section%I64u = [%I64u;%I64u] at %s\n"),
				(TIL_UINT64)s + 1, section.sampleOffset, lastSampleIndex, ((Til::String)section.start).c_str());
		}
		std::vector< std::vector<double> > mat;
		mat.resize(group.signals.size());
		sampleCount = group.sampleCount <= SIZE_MAX ? (size_t)group.sampleCount : SIZE_MAX;
		for (s = 0; s < group.signals.size(); s++) {
			Til::Signal &signal = group.signals[s];
			_tprintf(_T("\n  Signal %I64u/%I64u%s:\n"), (TIL_UINT64)s + 1, (TIL_UINT64)group.signals.size(),
				((s == 0) ? _T(" (= Reference Signal)") : _T("")));
			_tprintf(_T("    Name = %s\n"), signal.name.c_str());
			if (signal.unit.length()) _tprintf(_T("    Unit = %s\n"), signal.unit.c_str());
			_tprintf(_T("    DataType = %s\n"), GetDataTypeText(signal.raw.dataType, group.sampleCount));
			_tprintf(_T("    Factor = %lg\n"), signal.raw.factor);
			_tprintf(_T("    Offset = %lg\n"), signal.raw.offset);
			if (signal.raw.storage.fileName.length()) {
				_tprintf(_T("    FileName = %s\n"), signal.raw.storage.fileName.c_str());
				_tprintf(_T("    FileOffset = %I64u\n"), signal.raw.storage.offset);
				_tprintf(_T("    FileDataSize = %u\n"), signal.raw.storage.dataSize);
				_tprintf(_T("    FileGap = %u\n"), signal.raw.storage.gap);
			}
			_tprintf(_T("    FlagQuantized = %u\n"), signal.attributes.quantized ? 1 : 0);
			_tprintf(_T("    ViewMin = %lg\n"), signal.viewDefaults.min);
			_tprintf(_T("    ViewMax = %lg\n"), signal.viewDefaults.max);
			mat[s].resize(sampleCount);
			signal.iterator.Query(&mat[s][0], sampleCount);
		}
		_tprintf(_T("\n  Sample values:\n"));
		for (k = 0; k < sampleCount; k++) {
			for (s = 0; s < group.signals.size(); s++) {
				if (s == 0) _tprintf(_T("    "));
				_tprintf(_T("%lg"), mat[s][k]);
				_tprintf((s + 1) == group.signals.size() ? _T("\n") : _T("\t"));
			}
		}
	}

	return 0;
}

LPTSTR GetDataTypeText(unsigned dataType, TIL_UINT64 sampleCount)
{
#define BUFF_COUNT 256
	static _TCHAR str[BUFF_COUNT];
	switch (dataType){
	case dtSampleNumber:
		_sntprintf(str, BUFF_COUNT, _T("sample number [0;%I64u]; size: 0 bytes"), sampleCount - 1);
		return str;
	case dt_u8:
		return _T("unsigned char (Intel); size: 1 byte");
	case dt_s8:
		return _T("signed char (Intel); size: 1 byte");
	case dt_u16:
		return _T("unsigned short (Intel); size: 2 bytes");
	case dt_s16:
		return _T("signed short (Intel); size: 2 bytes");
	case dt_u32:
		return _T("unsigned long (Intel); size: 4 bytes");
	case dt_s32:
		return _T("signed long (Intel); size: 4 bytes");
	case dt_u64:
		return _T("unsigned __int64 (Intel); size: 8 bytes");
	case dt_s64:
		return _T("signed __int64 (Intel); size: 8 bytes");
	case dt_f32:
		return _T("float (Intel); size: 4 bytes");
	case dt_f64:
		return _T("double (Intel); size: 8 bytes");
	case dt_f80:
		return _T("long double (Intel); size: 10 bytes");
	}
	return _T("unknown");
}
