//-------------------------------------------------------------------------------------------
// <copyright file="SBGPCTDSensor_Sample.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 methods of SBGPCTDSensor's Sample inner class, which carries a reading.
// </summary>
//
// <owner>Mike Cookson</owner>
//-------------------------------------------------------------------------------------------

#include "SBGPCTDSensor.h"
#include "LqrSMACEscapeStr.h"
#include "nsextend.h"
#include <cmath>
#include <string>
#include <vector>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>

using namespace std;
using namespace LiquidRobotics::SMACFramework;

namespace LiquidRobotics {
namespace SeabirdGPCTD {

// Default constructor: all strings are empty and values are set to NAN
SBGPCTDSensor::Sample::Sample()
: tv(GetTimestamp())
, latitude(0.0)
, longitude(0.0)
, pressure(NAN)
, tempC(NAN)
, condSm(NAN)
, disOxyHz(NAN)
{
}

// Helper function to check whether there is a string at the given offset, attempt to
// convert it to float and return NAN if the conversion fails.  The string is copied to
// resultingString if found; otherwise, the resultingString is cleared.
inline float DoConvert(const vector<string>& strings, string& resultingString, size_t index)
{
	float result;

	if (index < strings.size()) {
		resultingString = strings[index];
		try			{ result = boost::lexical_cast<float>(resultingString); }
		catch(...)	{ result = NAN; }
	}
	else {
		result = NAN;
		resultingString.clear();
	}

	return result;
}

// Constructor with input line from sensor: values are converted and
// strings are set based on parsing the string
SBGPCTDSensor::Sample::Sample(const string& rawLine)
: tv(GetTimestamp())
, latitude(0.0)
, longitude(0.0)
, line(rawLine)
, pressure(NAN)
, tempC(NAN)
, condSm(NAN)
, disOxyHz(NAN)
{
	using namespace boost;
	vector<string> strings;
	string temp = trim_copy(line);
	split(strings, temp, is_any_of(" ,\t"), token_compress_on);

	pressure = DoConvert(strings, pressureStr, 0);
	tempC = DoConvert(strings, tempCStr, 1);
	condSm = DoConvert(strings, condSmStr, 2);
	disOxyHz = DoConvert(strings, disOxyHzStr, 3);
}

// Individual readings can be tested to see if a valid value
// was returned (not NAN)
bool SBGPCTDSensor::Sample::HaveReading(float readingValue)
{
	return !isnan(readingValue);
}

string SBGPCTDSensor::Sample::ToString() const
{
	stringstream msg;
	tm comp;
	localtime_r(&tv.tv_sec, &comp);

	msg << ultos(comp.tm_year+1900,10,4) << "/" << ultos(comp.tm_mon+1,10,2) << "/" << ultos(comp.tm_mday,10,2) << " "
	    << ultos(comp.tm_hour,10,2) << ":" << ultos(comp.tm_min,10,2) << ":" << ultos(comp.tm_sec,10,2)
	    << "." << ultos(tv.tv_usec,10,6)
	    << " lat=" << latitude << " lon=" << longitude
	    << " line='" << EscapeStr(line) << "' pressure=" << pressure << " tempC=" << tempC << " condSm=" << condSm << " disOxyHz=" << disOxyHz;
	return msg.str();
}

timeval SBGPCTDSensor::Sample::GetTimestamp()
{
	timeval result;

	if (gettimeofday(&result, NULL))
	{
		result.tv_sec = time(NULL);
		result.tv_usec = 0;
	}

	return result;
}


}
}
