/* 
	This function is mostly correct; the main issue is that we'd have to know
	when custom = 0, that we should use 'per theme' default sounds.
	We don't have those, we don't use those, those are an osu!-ism
	so the sounds are not going to be 100% osu!-correct
	but they're going to be correct enough for virtual-mode charts to be accurate.

	SampleSetAddition is an abomination on a VSRG - so it's only left in for informative purposes.
*/
GString GetSampleFilename(OsuLoadInfo *Info, SplitResult &Spl, int NoteType, int Hitsound, float Time)
{
	int SampleSet = 0, SampleSetAddition, CustomSample = 0;
	GString SampleFilename;

	if (!Spl.size()) // Handle this properly, eventually.
		return "normal-hitnormal.wav";

	size_t SplSize = Spl.size();

	if (NoteType & NOTE_HOLD)
	{
		if (SplSize > 5 && Spl[5].length())
			return Spl[5];

		if (Spl.size() == 4)
		{
			SampleSet = atoi(Spl[1].c_str());
			SampleSetAddition = atoi(Spl[2].c_str());
			CustomSample = atoi(Spl[3].c_str());
		}else
		{
			SampleSet = atoi(Spl[0].c_str());
			SampleSetAddition = atoi(Spl[1].c_str());
			CustomSample = atoi(Spl[2].c_str());
		}

		/*
		if (SplCnt > 4)
			Volume = atoi(Spl[4].c_str()); // ignored lol
			*/
	}else if (NoteType & NOTE_NORMAL)
	{
		if (SplSize > 4 && Spl[4].length())
			return Spl[4];

		SampleSet = atoi(Spl[0].c_str());
		if (Spl.size() > 1)
			SampleSetAddition = atoi(Spl[1].c_str());
		if (Spl.size() > 2)
			CustomSample = atoi(Spl[2].c_str());

		/*
		if (SplCnt > 3)
			Volume = atoi(Spl[3].c_str()); // ignored
			*/
	}else if (NoteType & NOTE_SLIDER)
	{
		SampleSet = SampleSetAddition = CustomSample = 0;
	}

	GString SampleSetGString;

	if (SampleSet)
	{
		// translate sampleset int into samplesetGString
		SampleSetGString = SamplesetFromConstant(SampleSet);
	}else
	{
		// get sampleset GString from sampleset active at starttime
		int Sampleset = -1;

		for (int i = 0; i < (int)Info->HitsoundSections.size() - (int)1; i++)
		{
			if (Info->HitsoundSections[i].Time <= Time && Info->HitsoundSections[i+1].Time < Time)
				Sampleset = Info->HitsoundSections[i].Sampleset;
			else if (Info->HitsoundSections[i+1].Time > Time)
				Sampleset = Info->HitsoundSections[i+1].Sampleset;
		}

		if (SampleSet == -1)
			SampleSetGString = Info->DefaultSampleset;
		else
			SampleSetGString = SamplesetFromConstant(Sampleset);
	}

	if (!CustomSample)
	{
		for (int i = 0; i < (int)Info->HitsoundSections.size()-(int)1; i++)
		{
			if (Info->HitsoundSections[i].Time <= Time && Info->HitsoundSections[i+1].Time < Time)
				CustomSample = Info->HitsoundSections[i].Custom;
			else if (Info->HitsoundSections[i+1].Time > Time)
				CustomSample = Info->HitsoundSections[i+1].Custom;
		}
	}

	GString CustomSampleGString;

	if (CustomSample)
		CustomSampleGString = Utility::IntToStr(CustomSample);

	GString HitsoundGString;

	if (Hitsound)
	{
		switch (Hitsound)
		{
		case 1:
			HitsoundGString = "normal";
			break;
		case 2:
			HitsoundGString = "whistle";
			break;
		case 4:
			HitsoundGString = "finish";
			break;
		case 8:
			HitsoundGString = "clap";
		default:
			break;
		}
	}else
		HitsoundGString = "normal";

	if (CustomSample > 1)
	{
		SampleFilename = SampleSetGString + "-hit" + HitsoundGString + CustomSampleGString + ".wav";
	}
	else
		SampleFilename = SampleSetGString + "-hit" + HitsoundGString + ".wav";

	return SampleFilename;
}
ModelData
ModelReader::Read(const std::string & path)
{
	std::ifstream file(path);

	if (!file.good())
	{
		throw std::runtime_error((boost::format("Failed to read file %s") % path).str());
	}

	PointVector points;
	NormaleVector normales;
	TextureCoords textures;
	IdsMap idsMap;

	ModelData md;

	std::string line;
	while (std::getline(file, line))
	{
		SplitResult res;

		boost::split(res, line, boost::is_any_of(" "));
	
		if (res.empty())
		{
			continue;
		}

		if (res[0] == "v")
		{
			RegisterVertex(res, points);
		}
		else if (res[0] == "vt")
		{
			RegisterTexture(res, textures);
		}
		else if (res[0] == "vn")
		{
			RegisterNormale(res, normales);
		}
		else if (res[0] == "f")
		{
			if (res.size() != 4)
			{
				throw std::runtime_error("Unexpected groups number for triangle");
			}

			SplitResult groupSplit;

			boost::split(groupSplit, res[1], boost::is_any_of("/"));
			RegisterGroup(groupSplit, points, textures, normales, idsMap, md);
			groupSplit.clear();

			boost::split(groupSplit, res[2], boost::is_any_of("/"));
			RegisterGroup(groupSplit, points, textures, normales, idsMap, md);
			groupSplit.clear();

			boost::split(groupSplit, res[3], boost::is_any_of("/"));
			RegisterGroup(groupSplit, points, textures, normales, idsMap, md);
		}
	}

	return md;
}