//-----------------------------------------------------------------------------------
// <copyright file="LqrSMACBooleanParser.cpp" company="LiquidRobotics">
//
// Copyright (c) 2014 Liquid Robotics, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// This software is associated with a release.  Liquid Robotics makes no
// representation that the design, interfaces or component distribution will
// remain unchanged in future releases.
//
// </copyright>
//
// <summary>
//   Implementation of standardized boolean to string and string to boolean functions
// </summary>
//
// <owner>Mike Cookson</owner>
//-----------------------------------------------------------------------------------

#include "LqrSMACBooleanParser.h"
#include <sstream>
#include <stdexcept>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>

using namespace std;
using namespace boost;

static const string trueStr = "true";
static const string falseStr = "false";
static const string tStr = "t";
static const string fStr = "f";
static const string yesStr = "yes";
static const string noStr = "no";
static const string yStr = "y";
static const string nStr = "n";
static const string onStr = "on";
static const string offStr = "off";
static const string _0Str = "0";
static const string _1Str = "1";
static const string __1Str = "-1";

namespace LiquidRobotics {
namespace SMACFramework {

const std::string& BooleanToString(bool val)
{
	return val ? trueStr : falseStr;
}

bool StringToBoolean(const string& val)				// throws exceptions
{
	bool result;

	if (!StringToBoolean(val, result))
	{
		stringstream msg;
		const string sep = ", ";

		msg << "boolean must be on of: "
			<< trueStr
			<< sep << falseStr
			<< sep << tStr
			<< sep << fStr
			<< sep << yesStr
			<< sep << noStr
			<< sep << yStr
			<< sep << nStr
			<< sep << onStr
			<< sep << offStr
			<< sep << _0Str
			<< sep << _1Str << " or " << __1Str;

		const string msgStr = msg.str();
		throw invalid_argument(msgStr);
	}

	return result;
}

bool StringToBoolean(const string& val, bool& result)	// returns true if successful, false on error
{
	bool retVal = true;

	string tVal = val;
	trim(tVal);

	if (iequals(tVal, trueStr) || iequals(tVal, tStr) || iequals(tVal, yesStr) || iequals(tVal, yStr) || iequals(tVal, onStr))
		result = true;
	else if (iequals(tVal, falseStr) || iequals(tVal, fStr) || iequals(tVal, noStr) || iequals(tVal, nStr) || iequals(tVal, offStr))
		result = false;
	else
	{
		int num;

		try			{ num = lexical_cast<int>(tVal); }
		catch(...)	{ retVal = false; }

		if (retVal)
		{
			if ((num < -1) || (num > 1))
				retVal = false;
			else
				result = !!num;
		}
	}

	return retVal;
}

}
}
