/*
	PIP - Platform Independent Primitives
	Global includes
	Ivan Pelipenko peri4ko@yandex.ru

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "piincludes.h"
#include "piincludes_p.h"
#include "pitime.h"
#ifndef QNX
#  include <clocale>
#else
#  include <locale.h>
#endif
#ifdef MAC_OS
//#  include <mach/mach_traps.h>
//#  include <mach/mach.h>
#  include <mach/clock.h>
//#  include <crt_externs.h>
#endif
#include <errno.h>

bool piDebug = true;
double piMountInfoRefreshIntervalMs = 10000.;

lconv * currentLocale =
#ifdef ANDROID
		0;
#else
		std::localeconv();
#endif

#ifdef MAC_OS
clock_serv_t __pi_mac_clock;
#endif

#ifdef WINDOWS
FILETIME __pi_ftjan1970;
long long __pi_perf_freq = -1;
PINtQueryTimerResolution getTimerResolutionAddr = 0;
PINtSetTimerResolution setTimerResolutionAddr = 0;
#endif

void errorClear() {
#ifdef WINDOWS
	SetLastError(0);
#else
	errno = 0;
#endif
}

PIString errorString() {
#ifdef WINDOWS
	char * msg;
	int err = GetLastError();
	FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, NULL);
	return "code " + PIString::fromNumber(err) + " - " + PIString(msg);
#else
	int e = errno;
	return PIString("code ") + PIString::fromNumber(e) + " - " + PIString(strerror(e));
#endif
}

PIString PIPVersion() {
	static PIString ret = PIStringAscii(PIP_VERSION_NAME);
	return ret;
}


void piqsort(void * base, size_t num, size_t size, int (*compar)(const void *, const void *)) {
	qsort(base, num, size, compar);
}


void randomize() {
	srand(PISystemTime::current(true).nanoseconds);
}


int randomi() {
	return rand();
}


/*! \class PICout
 * \brief Class for formatted output similar std::cout
 * 
 * \section PICout_sec0 Synopsis
 * This class provide many stream operators for output with some features.
 * Output to PICout is thread-sequential, i.e. doesn`t mixed from parallel
 * threads.
 * 
 * \section PICout_sec1 Features
 * - insertion spaces between entries
 * - insertion new line at the end of output
 * - strings are quoted
 * - custom output operator can be easily written
 * 
 * \section PICout_ex0 Usage
 * \snippet picout.cpp 0
 * 
 * \section PICout_ex1 Writing your own output operator
 * \snippet picout.cpp own
 */


/*! \mainpage What is PIP
 * PIP - Platform-Independent Primitives - is crossplatform library for C++ developers.
 * It is wrap around STL and pure C++. This library can help developers write non-GUI
 * projects much more quickly, efficiently and customizable than on pure C++.
 * Library contains many classes, some of them are pure abstract, some classes
 * can be used as they are, some classes should be inherited to new classes.
 * PIP provide classes:
 * * direct output to console (\a PICout)
 * * containers (\a PIVector, \a PIList, \a PIMap, \a PIStack)
 * * byte array (\a PIByteArray)
 * * string (\a PIString, \a PIStringList)
 * * base object (events and handlers) (\a PIObject)
 * * multithreading
 *  * thread (\a PIThread)
 *  * executor (\a PIThreadPoolExecutor)
 *  * blocking dequeue (\a PIBlockingDequeue)
 * * timer (\a PITimer)
 * * console (information output) (\a PIConsole)
 *  * stand-alone
 *  * server
 *  * client
 * * I/O devices
 *  * base class (\a PIIODevice)
 *  * file (\a PIFile)
 *  * serial port (\a PISerial)
 *  * ethernet (\a PIEthernet)
 *  * USB (\a PIUSB)
 *  * packets extractor (\a PIPacketExtractor)
 *  * binary log (\a PIBinaryLog)
 *  * complex I/O point (\a PIConnection)
 * * Run-time libraries
 *  * abstract (\a PILibrary)
 *  * plugin (\a PIPluginLoader)
 * * connection quality diagnotic (\a PIDiagnostics)
 * * command-line arguments parser (\a PICLI)
 * * math evaluator (\a PIEvaluator)
 * * peering net node (\a PIPeer)
 * * process (\a PIProcess)
 * * state machine (\a PIStateMachine)
 * \n \n Basic using of PIP described at page \ref using_basic */


/*! \page using_basic Getting started
 * Many novice programmers are solved many common task with system integrity: output to console,
 * keyboard buttons press detecting, working with serial ports, ethernet or files, and many other.
 * These tasks can solve this library, and code, based only on PIP will be compile and work
 * similar on many systems: Windows, any Linux, Red Hat, FreeBSD, MacOS X and QNX.
 * Typical application on PIP looks like this: \n
\code{.cpp}
#include <pip.h>


// declare key press handler
void key_event(char key, void * );


PIConsole console(false, key_event); // don`t start now, key handler is "key_event"


// some vars
int i = 2, j = 3;


// implicit key press handler
void key_event(char key, void * ) {
	switch (key) {
	case '-':
		i--;
		break;
	case '+':
		i++;
		break;
	case '(':
		j--;
		break;
	case ')':
		j++;
		break;
	};
};


class MainClass: public PITimer {
	PIOBJECT(MainClass)
public:
	MainClass() {}
protected:
	void tick(void * data, int delimiter) {
		piCout << "timer tick";
		// timer tick
	}
};


MainClass main_class;


int main(int argc, char * argv[]) {
	// enabling auto-detection of exit button press, by default 'Q' (shift+q)
	console.enableExitCapture();
	
	// if we want to parse command-line arguments
	PICLI cli(argc, argv);
	cli.addArgument("console"); // "-c" or "--console"
	cli.addArgument("debug"); // "-d" or "--debug"
	
	// enabling or disabling global debug flag
	piDebug = cli.hasArgument("debug");
	
	// configure console
	console.addTab("first tab", '1');
	console.addString("PIP console", 1, PIConsole::Bold);
	console.addVariable("int var (i)", &i, 1);
	console.addVariable("int green var (j)", &j, 1, PIConsole::Green);
	console.addString("'-' - i--", 2);
	console.addString("'+' - i++", 2);
	console.addString("'(' - j--", 2);
	console.addString("')' - j++", 2);
	console.addTab("second tab", '2');
	console.addString("col 1", 1);
	console.addString("col 2", 2);
	console.addString("col 3", 3);
	console.setTab("first tab");
	
	// start output to console if "console" argument exists
	if (cli.hasArgument("console"))
		console.start();
	
	// start main class, e.g. 40 Hz
	main_class.start(25.);
	
	// wait for 'Q' press, independently if console is started or not
	console.waitForFinish();
	
	return 0;
};
\endcode
 * This code demonstrates simple interactive configurable program, which can be started with console
 * display or not, and with debug or not. \b MainClass is central class that also can be inherited from
 * \a PIThread and reimplement \a run() function.
 * \n Many PIP classes has events and event handlers, which can be connected one to another.
 * Details you can see at \a PIObject reference page (\ref PIObject_sec0).
 * \n To configure your program from file use \a PIConfig.
 * \n If you want more information see \ref using_advanced */


/*! \page using_advanced Advanced using
 * Sorry, creativity crysis xD
 */
