/*! 
*   \file  CMetaData.h
*   \brief Declares class to hold signature of image.
*    
*   \details  
*   CMetaData is a container of image-specific signature. 
*
*   \date     July 2013
*   \copyright eBay Research Labs.
*/

#pragma once

// Include standard C++ headers.
#include <string>  
#include <algorithm>
#include "CMetaData.h"


const std::string 
	CMetaData::BuyingFormatNoneStr = "", 
	CMetaData::BuyingFormatAnyStr =  "Any", 
	CMetaData::BuyingFormatAuctionStr = "Auction",
	CMetaData::BuyingFormatBuyItNowStr = "BuyNow" ;

const std::string 
	CMetaData::ConditionNoneStr = "",
	CMetaData::ConditionAnyStr = "All",
	CMetaData::ConditionNewWithTagsStr = "NewWithTags",
	CMetaData::ConditionNewWithoutTagsStr = "NewWithoutTags", 
	CMetaData::ConditionNewWithDefectsStr = "NewWithDefects",
	CMetaData::ConditionPreOwnedStr = "PreOwned";  

const std::string	
	CMetaData::FormatStr = "ItemFormat",
	CMetaData::SizeTypeStr	 = "ItemSizeType",
	CMetaData::SizeStr	 = "ItemSize",
	CMetaData::PriceStr  = "ItemPrice",
	CMetaData::PriceMaxStr = "ItemPriceMax",
	CMetaData::BrandStr = "ItemBrand",
	CMetaData::ConditionStr = "ItemCondition";

CMetaData::CMetaData():
	m_version(CurrentVersion),  m_BuyingFormat(CMetaData::BuyingFormatNone), m_Condition(CMetaData::ConditionNone), m_Price(-1.)
{

}

CMetaData::BuyingFormats CMetaData::GetFormatFromSaleType(const std::string& saletype)
{
	if (saletype == "Chinese" || saletype == "Dutch" ||saletype == "Auction" || saletype == "Live" || saletype == "PersonalOffer")
		return CMetaData::BuyingFormatAuction;
	else
		return CMetaData::BuyingFormatBuyItNow ;
}
												

CMetaData::BuyingFormats CMetaData::GetFormatFromString(const std::string& format)
{    
	CMetaData::BuyingFormats ret(CMetaData::BuyingFormatNone);

	if (format.empty() || format == CMetaData::BuyingFormatAnyStr )
		ret = CMetaData::BuyingFormatAny ;
		else if ( format== CMetaData::BuyingFormatAuctionStr )
		ret = CMetaData::BuyingFormatAuction ;
		else if ( format == CMetaData::BuyingFormatBuyItNowStr )
		ret = CMetaData::BuyingFormatBuyItNow ;
		return ret;
}


CMetaData::ItemConditions CMetaData::GetConditionFromString(const std::string& condition)
{
		CMetaData::ItemConditions ret(ConditionAny);
		if ( condition == CMetaData::ConditionNewWithTagsStr )
			ret = CMetaData::ConditionNewWithTags;
		else if ( condition == CMetaData::ConditionNewWithoutTagsStr )
			ret = CMetaData::ConditionNewWithoutTags;
		else if ( condition == CMetaData::ConditionNewWithDefectsStr )
			ret = CMetaData::ConditionNewWithDefects;
		else if ( condition == CMetaData::ConditionPreOwnedStr )
			ret = CMetaData::ConditionPreOwned;
		return ret;
}

CMetaData::CMetaData(const std::string& saletype, const std::string& condition, const std::string&  brand, const std::string& sizeType, const std::string& size,  const std::string& price): 
	m_version(CurrentVersion),  m_BuyingFormat(GetFormatFromSaleType(saletype)), m_Condition(GetConditionFromString(condition)), 
			m_Brand(brand), m_SizeType(sizeType),  m_Size(size), 
			m_Price(std::atof(price.c_str()))
{ 

}

bool CMetaData::matches(const CMetaDataQuery& q) const
{
	if (!(m_Condition & q.m_ConditionSet))
		return false;
	if (!(m_BuyingFormat & q.m_BuyingFormatSet))
		return false;
	if (m_Price < q.m_PriceMin || m_Price > q.m_PriceMax)
		return false;
	if (q.m_BrandSet.size() > 0 && std::find(q.m_BrandSet.begin(), q.m_BrandSet.end(), m_Brand) == q.m_BrandSet.end()) 
		return false;
	if (q.m_SizeType.size() > 0 && q.m_SizeType != SizeType() )
		return false;
	if (q.m_SizeSet.size() > 0 && std::find(q.m_SizeSet.begin(), q.m_SizeSet.end(), m_Brand) == q.m_SizeSet.end())
		return false;
	return true;
}

const std::string& CMetaData::ConditionAsString(CMetaData::ItemConditions condition)
{
	switch(condition)
	{
	case CMetaData::ConditionNone:
	default:
		return CMetaData::ConditionNoneStr;
    case CMetaData::ConditionAny:
		return CMetaData::ConditionAnyStr;
	case CMetaData::ConditionNewWithTags:
		return CMetaData::ConditionNewWithTagsStr;
	case CMetaData::ConditionNewWithoutTags:
		return CMetaData::ConditionNewWithoutTagsStr;
	case CMetaData::ConditionNewWithDefects:
		return CMetaData::ConditionNewWithDefectsStr;
	case CMetaData::ConditionPreOwned:
		return CMetaData::ConditionPreOwnedStr;
	}
}

const std::string& CMetaData::BuyingFormatAsString(CMetaData::BuyingFormats format)
{
	switch (format)
	{
	case CMetaData::BuyingFormatAny:
		return CMetaData::BuyingFormatAnyStr;
	case CMetaData::BuyingFormatAuction:
		return CMetaData::BuyingFormatAuctionStr;
	case CMetaData::BuyingFormatBuyItNow:
		return CMetaData::BuyingFormatBuyItNowStr;
	case CMetaData::BuyingFormatNone:
	default:
		return CMetaData::BuyingFormatNoneStr;
	}
}

const std::string& CMetaData::BuyingFormat() const
{
	return BuyingFormatAsString(m_BuyingFormat);
}

const std::string& CMetaData::Condition() const
{
	return ConditionAsString(m_Condition);
}

CMetaDataQuery::CMetaDataQuery(): 
	m_version(CMetaData::CurrentVersion),  
			m_ConditionSet(CMetaData::ConditionAny),  m_BuyingFormatSet(CMetaData::BuyingFormatAny),
				m_PriceMin(0), m_PriceMax(10000000.0) 
{ }

void CMetaDataQuery::addCondition(const std::string& c)
{
	m_ConditionSet |= CMetaData::GetConditionFromString(c);
}

void CMetaDataQuery::addFormat(const std::string& f)
{
	m_BuyingFormatSet |= CMetaData::GetFormatFromString(f);
}

void CMetaDataQuery::addBrand(const std::string& b)
{
	m_BrandSet.push_back(b);
}

void CMetaDataQuery::addSize(const std::string& s)
{
	m_SizeSet.push_back(s);
}

void CMetaDataQuery::setSizeType(const std::string& s)
{
	m_SizeType = s;
}

void CMetaDataQuery::setPriceRange(const std::string& minP, const std::string& maxP)
{
	m_PriceMax = std::atof(maxP.c_str());
	m_PriceMin = std::atof(minP.c_str());

}