#ifndef __TILCLASS_H
#define __TILCLASS_H

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

#pragma warning(disable : 4786)

#include <Windows.h>
#include <map>
#include <string>
#include <vector>
#include "til.h"

class Til {
public:
		
	class AnsiString : public std::string {
	public:
		void clear() { assign(""); }
		const AnsiString & operator = (TIL_PPROP prop);
	};

	class String : public std::basic_string<TIL_TCHAR> {
	public:
		AnsiString ansiString;
		void clear() { assign(TIL_T("")); }
		const String & operator = (TIL_PPROP prop);
	};

	class Timestamp {
		TIL_TIME64 time;
	public:
		Timestamp() { time = 0; }
		bool IsValid() const { return time != 0; }
		operator TIL_TIME64() const { return time; }
		TIL_TIME64 operator = (TIL_TIME64 t) { time = t; return time; }
		operator FILETIME() const;
		operator SYSTEMTIME() const;
		operator TIL_DATETIME() const;
		operator String() const;
	};

	class Variant {
		enum { NONE, DBL, STR };
		unsigned type;
		double dbl;
		String str;
	public:
		Variant() { type = NONE; dbl = 0; }
		Variant(const double &d) { type = DBL; dbl = d; }
		Variant(const String &s) { type = STR; dbl = 0; str = s; }
		const double& operator = (const double &d) { type = DBL; dbl = d; str.clear(); return dbl; }
		const String& operator = (const String &s) { type = STR; dbl = 0; str = s; return str; }
		unsigned Type() const { return type; }
		operator double() const { return dbl; }
		operator String() const { return str; }
	};
	class Variables : public std::map<String, Variant> {
	public:
		bool Load(TIL_PPROP prop);
	};

	class Section {
	public:
		TIL_UINT64 sampleOffset;
		Timestamp start;
		Section() { sampleOffset = 0; }
		bool Load(TIL_PPROP prop);
	};
	typedef std::vector<Section> Sections;

	class Time {
	public:
		Timestamp deviceSetup;
		Timestamp start;
		Timestamp deviceReadOut;
		Sections sections;
		bool Load(TIL_PPROP prop);
	};

	class Attributes {
	public:
		bool quantized;
		Attributes() { quantized = false; }
		bool Load(TIL_PPROP prop);
	};

	class ViewDefaults {
	public:
		double min;
		double max;
		ViewDefaults() { min = max = 0; }
		bool Load(TIL_PPROP prop);
	};

	class Storage {
	public:
		String fileName;
		TIL_UINT64 offset;
		unsigned dataSize;
		unsigned gap;
		Storage() { offset = 0; dataSize = gap = 0; }
		bool Load(TIL_PPROP prop);
	};
	
	class Iterator {
		unsigned dataType;
		size_t itemSize;
		TIL_UINT64 itemCount;
		TIL_PPROP iterator;
	public:
		Iterator() { dataType = 0; itemSize = 0; itemCount = 0; iterator = NULL; }
		size_t ItemSize() const { return itemSize; }
		TIL_UINT64 ItemCount() const { return itemCount; }
		unsigned DataType() const { return dataType; }
		bool Load(TIL_PPROP prop, unsigned dataType, TIL_UINT64 itemCount);
		bool IsAvailable() const { return iterator != NULL; }
		bool Rewind() { return TilRewindIterator(iterator) != 0; }
		bool Query(void *dest, size_t count) { return TilGetNextIteratorItems(iterator, dest, count) != 0; }
	};

	class Raw {
	public:
		unsigned dataType;
		double factor;
		double offset;
		Storage storage;
		Iterator iterator;
		Raw() { dataType = 0; factor = offset = 0; }
		bool Load(TIL_PPROP prop, TIL_UINT64 sampleCount);
	};

	class Marker {
	public:
		String name;
		TIL_INT64 sampleIndex;
		bool visibleAttribute;
		unsigned type;
		String text;
		int textAngle;
		int textDistance;
		Marker() { sampleIndex = -1; visibleAttribute = false; type = 0; textAngle = textDistance = -1; }
		bool IsSampleIndexValid() const { return sampleIndex >= 0; }
		bool IsVisible() const { return visibleAttribute && IsSampleIndexValid(); }
		bool IsTextAngleValid() const { return textAngle >= 0; }
		bool IsTextDistanceValid() const { return textDistance >= 0; }
		bool Load(TIL_PPROP prop);
	};
	typedef std::vector<Marker> Markers;

	class Group;
	class Signal {
	public:
		String name;
		String comment;
		Variables variables;
		String unit;
		Raw raw;
		Attributes attributes;
		ViewDefaults viewDefaults;
		Markers markers;
		Iterator iterator;
		Group *group;
		Signal() { group = NULL; }
		bool Load(TIL_PPROP prop, Group *group);
	};
	typedef std::vector<Signal> Signals;

	class Group {
	public:
		String name;
		String comment;
		TIL_UINT64 sampleCount;
		double sampleRate;
		Time time;
		Signals signals;
		Variables variables;
		bool Load(TIL_PPROP prop);
	};
	typedef std::vector<Group> Groups;

	class SignalInfo {
	public:
		unsigned measIndex;
		unsigned groupIndex;
		unsigned signalIndex;
		const Signal *signal;
		const Signal *refSignal;
		SignalInfo() { measIndex = groupIndex = signalIndex = 0; signal = refSignal = NULL; }
		bool IsRefSignal() const { return signalIndex == 0; }
		bool Load(TIL_PPROP prop, const Groups &groups);
	};

	class ViewItem {
	public:
		SignalInfo info;
		String name;
		String unit;
		double factor;
		double offset;
		double refFactor;
		double refOffset;
		bool slotVisibleAttribute;
		bool curveVisibleAttribute;
		int digits;
		unsigned curveColor;
		unsigned curveThickness;
		unsigned curveLinePattern;
		double begin;
		double end;
		int axisPosition;
		int xAxisPosition;
		double axisMin;
		double axisMax;
		String axisName;
		String axisTitle;
		double axisDefaultMin;
		double axisDefaultMax;

		ViewItem() { 
			factor = refFactor = 1; offset = refOffset = 0; slotVisibleAttribute = false;
			curveVisibleAttribute = false; digits = 0; curveColor = curveThickness =
			  curveLinePattern = 0; begin = end = 0; axisPosition = xAxisPosition = 0;
			axisMin = axisMax = axisDefaultMin = axisDefaultMax = 0;

		}
		bool IsSlotVisible() const { return slotVisibleAttribute; }
		bool IsCurveVisible() const { return curveVisibleAttribute; }
		bool Load(TIL_PPROP prop, const Groups &groups);
	};
	typedef std::vector<ViewItem> ViewItems;

	class View {
	public:
		String name;
		ViewItems viewItems;
		bool Load(TIL_PPROP prop, const Groups &groups);
	};
	typedef std::vector<View> Views;

protected:
	TIL_POBJECT obj;
	unsigned version;
public:
	String fileName;
	Groups groups;
	Variables variables;
	Views views;
	Til() { obj = NULL; version = 0; }
	~Til() { if (obj) TilDestroyObject(obj); }
	void Clear();
	bool Load(TIL_PCTSTR fileName);

	unsigned GetVersion() {
		return version;
	}
	static void GetValue(TIL_PCPROP pProperty, bool *pBool, bool def = false) {
		TIL_BOOL tmpBool = (TIL_BOOL)def;
		TilGetBool(pProperty, &tmpBool);
		if (pBool) *pBool = tmpBool != 0;
	}
	static void GetValue(TIL_PCPROP pProperty, int *pInt, int def = 0) {
		if (!TilGetInt(pProperty, pInt)) if (pInt) *pInt = def;
	}
	static void GetValue(TIL_PCPROP pProperty, unsigned *pUInt, unsigned def = 0) {
		if (!TilGetUInt(pProperty, pUInt)) if (pUInt) *pUInt = def;
	}
	static void GetValue(TIL_PCPROP pProperty, TIL_PINT64 pInt64, TIL_INT64 def = 0) {
		if (!TilGetInt64(pProperty, pInt64)) if (pInt64) *pInt64 = def;
	}
	static void GetValue(TIL_PCPROP pProperty, TIL_PUINT64 pUInt64, TIL_UINT64 def = 0) {
		if (!TilGetUInt64(pProperty, pUInt64)) if (pUInt64) *pUInt64 = def;
	}
	static void GetValue(TIL_PCPROP pProperty, TIL_PFLOAT64 pFloat64, TIL_FLOAT64 def = 0) {
		if (!TilGetFloat64(pProperty, pFloat64)) if (pFloat64) *pFloat64 = def;
	}
	static void GetValue(TIL_PCPROP pProperty, Timestamp *timestamp, TIL_TIME64 def = 0) {
		TilGetTime64(pProperty, &def);
		if (timestamp) *timestamp = def;
	}
};

#endif
