/*
 * serialize.cc: object serialization functions
 *
 * This file is part of Pyrit Ray Tracer.
 *
 * Copyright 2008  Radek Brich
 *
 * 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.
 */

#include "serialize.h"
#include <vector>
#include <string>
#include <sstream>

Indexer vertex_index, shape_index;
vector<Vertex*> vertices;

void resetSerializer()
{
	vertex_index.reset();
	shape_index.reset();
	vertices.clear();
}

bool Indexer::get(void *o, int &retidx)
{
	map <void *, int>::iterator i;
	i = indexmap.find(o);
	if (i == indexmap.end())
	{
		retidx = index++;
		indexmap[o] = retidx;
		return false;
	}
	else
	{
		retidx = i->second;
		return true;
	}
}

Shape *loadShape(istream &st, Material *mat)
{
	string s;
	istringstream is;
	for (;;)
	{
		getline(st, s, ',');
		trim(s);

		// Vertex
		if (s.compare("(v") == 0)
		{
			Vector3 P;
			st >> P;
			getline(st, s, ')');
			vertices.push_back(new Vertex(P));
			getline(st, s, ',');
			continue;
		}

		// NormalVertex
		if (s.compare("(vn") == 0)
		{
			Vector3 P,N;
			st >> P;
			getline(st, s, ',');
			st >> N;
			getline(st, s, ')');
			vertices.push_back(new NormalVertex(P,N));
			getline(st, s, ',');
			continue;
		}

		// Triangle
		if (s.compare("(t") == 0)
		{
			int a,b,c;
			st >> a;
			getline(st, s, ',');
			st >> b;
			getline(st, s, ',');
			st >> c;
			getline(st, s, ')');
			return new Triangle(vertices[a], vertices[b], vertices[c], mat);
		}

		// box
		if (s.compare("(box") == 0)
		{
			Vector3 L,H;
			st >> L;
			getline(st, s, ',');
			st >> H;
			getline(st, s, ')');
			return new Box(L, H, mat);
		}

		// Sphere
		if (s.compare("(sphere") == 0)
		{
			Vector3 center;
			Float radius;
			st >> center;
			getline(st, s, ',');
			st >> radius;
			getline(st, s, ')');
			return new Sphere(center, radius, mat);
		}

		// else...
		return NULL;
	}
}

ostream & operator<<(ostream &st, Shape &o)
{
	return o.dump(st);
}

ostream & operator<<(ostream &st, Vertex &o)
{
	return o.dump(st);
}

ostream & operator<<(ostream &st, Container &o)
{
	return o.dump(st);
}
