// Local
#include "config.h"

// STDC++
#include <iostream>
#include <string>

// POSIX C

// C++ Libraries
#include <ui-utilcpp/File.hpp>
#include <ui-utilcpp/Misc.hpp>
#include <ui-utilcpp/Thread.hpp>

using UI::Util::MutexLock;
using UI::Util::FileDescriptor;
using UI::Util::PosixFileMutex;
using UI::Util::BSDFileMutex;

template <typename M>
int lock(const std::string & fileName)
{
	int exitCode(0);
	try
	{
		M m(fileName);
		MutexLock<M> l(m, false);
		std::cout << "Locked (do some input to finish): " << fileName << std::flush;
		std::string dummy;
		std::cin >> dummy;
	}
	catch(typename MutexLock<M>::Exception const & ex)
	{
		std::cerr << "MutexLock exception: " << ex.getCode() << ": " << ex.what() << std::endl;
		exitCode = 1;
	}
	catch(typename M::Exception const & ex)
	{
		std::cerr << "FileLock exception: " << ex.getCode() << ": " << ex.what() << std::endl;
		exitCode = 2;
	}
	catch(std::exception const & ex)
	{
		std::cerr << "std::exception: " << ex.what() << std::endl;
		exitCode = 3;
	}
	catch(...)
	{
		std::cerr << "ERROR: Unknown exception!" << std::endl;
		exitCode = 4;
	}
	return(exitCode);
}

int main(int argc, char *argv[])
{
	if (argc != 3)
	{
		std::cerr << "Lock a file via POSIX or BSD advisory locking." << std::endl << std::endl;
		std::cerr << "Usage: " << argv[0] << " posix|bsd <file>" << std::endl << std::endl;
		std::cerr << "Exit Codes: 0 for success, 1 if file was locked, 2 if creat(2) failed, 3 for unknown error." << std::endl;
		std::cerr << "Exit Codes: 42 for some other error." << std::endl;
		return(42);
	}

	if ((std::string) argv[1] == "posix")
	{
		return(lock<PosixFileMutex>(argv[2]));
	}
	else if ((std::string) argv[1] == "bsd")
	{
		return(lock<BSDFileMutex>(argv[2]));
	}
	else
	{
		std::cerr << "Argument 1 must be either \"posix\" or \"bsd\"." << std::endl;
		return(42);
	}
}
