//
// C++ Implementation: scene_object
//
// Description:
//
//
// Author: Denis A. Birukov <denis.birukov@gmail.com>, (C) 2008
//
// Copyright: See COPYING file that comes with this distribution
//
//

#include "sceneobject.h"
#include "video_int.h"
#include "video.h"
#include "signal_manager.h"
#include <stdio.h>

bool SceneObject::load ( std::string storage_name, std::string storage_prefix, std::string scene_name, std::string object_name )
{
	_scene_name_ = scene_name;
	_object_name_ = object_name;
	Config_Interface *intf = config_get_interface ( storage_name );
	if ( !intf )
	{
		_set_error ( "Can't get config interface:" + config_error() );
		return false;
	}
	std::string coord_type = intf->_get_value ( storage_prefix + "coord", "" );
	if ( coord_type == "absolute" )
	{
		_x_ = atof ( intf->_get_value ( storage_prefix + "absolute->x_pos", "0.0" ).c_str() );
		_y_ = atof ( intf->_get_value ( storage_prefix + "absolute->y_pos", "0.0" ).c_str() );
		std::cerr << "x:" << _x_ << " y:" << _y_ << std::endl;
	}
	else if ( coord_type == "link" )
	{
		Video_Interface *vid = video_get_interface ( _video_name_ );
		if ( !vid )
		{
			_set_error ( "Can't get video interface:" + video_error() );
			return false;
		}
		std::string object_name;
		object_name = intf->_get_value ( storage_prefix + "link->object", "" );

		Video_Sprite *spr;
		spr = vid->_get_sprite ( object_name, scene_name );
		if ( !spr )
		{
			_set_error ( "Can't get sprite: " + vid->_get_error() );
			return false;
		}
		std::string v_align, h_align;
		float v_offset, h_offset;
		v_align = intf->_get_value ( storage_prefix + "link->v_align", "center" );
		h_align = intf->_get_value ( storage_prefix + "link->h_align", "center" );

		v_offset = atof ( intf->_get_value ( storage_prefix + "link->v_offset", "0.0" ).c_str() );
		h_offset = atof ( intf->_get_value ( storage_prefix + "link->h_offset", "0.0" ).c_str() );

		VideoRect scoord;
		spr->_get_rectangle ( &scoord );
		if ( v_align == "top" ) _y_ = scoord.y_e;
		else if ( v_align == "bottom" ) _y_ = scoord.y_s;
		else if ( v_align == "center" ) _y_ = scoord.y_s + ( scoord.y_e - scoord.y_s ) / 2.;
		else if ( v_align == "base_point" ) _y_ = spr->_get_y() + spr->_get_base_y();
		else
		{
			_set_error ( "Unknown v_align kind: \"" + v_align + "\"" );
			return false;
		}
		_y_ += spr->_get_v_offset ( v_offset );
		if ( h_align == "left" ) _x_ = scoord.x_s;
		else if ( h_align == "right" ) _x_ = scoord.x_e;
		else if ( h_align == "center" ) _x_ = scoord.x_s + ( scoord.x_e - scoord.x_s ) / 2.;
		else if ( h_align == "base_point" ) _x_ = spr->_get_x() + spr->_get_base_x();
		else
		{
			_set_error ( "Unknown h_align kind: \"" + h_align + "\"" );
			return false;
		}
		_x_ += spr->_get_h_offset ( h_offset );
		std::cerr << "x:" << _x_ << " y:" << _y_ << std::endl;
	}
	else
	{
		_set_error ( "Unknown coord kind: " + coord_type );
		return false;
	}
	load_signals ( intf, storage_prefix );
	return true;
};
void SceneObject::_get_active_area_rect ( VideoRect * rect )
{
	rect->x_s = 0;
	rect->y_s = 0;
	rect->x_e = 0;
	rect->y_e = 0;
	Video_Interface *vid = video_get_interface ( _video_name_ );
	if ( !vid ) return;
	Video_Sprite *spr = vid->_get_sprite ( _object_name_, _scene_name_ );
	if ( !spr ) return;
	spr->_get_rectangle ( rect );
//    std::cerr << _object_name_ << "--Rect:[" << rect->x_s << ";" << rect->y_s<< "] -> [" << rect->x_e << ";" << rect->y_e<<"]"<< std::endl;
}

void SceneObject::load_signals ( Config_Interface *intf, std::string storage_prefix )
{
	std::cerr << __FUNCTION__ << std::endl;
	char number[9];
	std::string prefix = storage_prefix + "signals->signal";
	std::cerr << "prefix=" << prefix << std::endl;
	register_slots();

	//Добавим дефолтные сигналы
	SignalName signal_name_t = _scene_name_ + "->activate";
	SlotName slot_name_t = _scene_name_ + "->" + _object_name_ + "->on_activate";
	_signal_connections_.push_back ( SignalConnection ( signal_name_t, slot_name_t ) );

	signal_name_t = _scene_name_ + "->deactivate";
	slot_name_t = _scene_name_ + "->" + _object_name_ + "->on_deactivate";
	_signal_connections_.push_back ( SignalConnection ( signal_name_t, slot_name_t ) );

	signal_name_t = _scene_name_ + "->reinit";
	slot_name_t = _scene_name_ + "->" + _object_name_ + "->on_scene_reinit";
	_signal_connections_.push_back ( SignalConnection ( signal_name_t, slot_name_t ) );
	
	for ( int a = 0;a < 1000000;a++ )
	{
		snprintf ( number, 8, "%d->", a );
		std::string connect_type = intf->_get_value ( prefix + number + "connect", "on_request" );
		std::string type = intf->_get_value ( prefix + number + "type", "custom" );
		std::string signal_source = intf->_get_value ( prefix + number + "signal_source", "" );
		if ( signal_source.length() == 0 ) break;
		std::string signal_name = intf->_get_value ( prefix + number + "signal_name", "" );
		std::string slot_name = intf->_get_value ( prefix + number + "slot_name", "" );

		if ( signal_name == "activate" || signal_name == "deactivate" || !signal_name.length() ) continue;
		if ( type == "builtin" )
		{
			if ( signal_source == "Video" ) signal_source = _video_name_;
		}
		signal_name_t = signal_source + "->" + signal_name;
		slot_name_t = _scene_name_ + "->" + _object_name_ + "->" + slot_name;
		std::cerr << "SlotName: " << slot_name_t << std::endl;
		_signal_connections_.push_back ( SignalConnection ( signal_name_t, slot_name_t ) );


		std::cerr << "CONNECT_TYPE: " << connect_type << std::endl;
		//Если режим connect: on_load сразу производим соединение сигнала
		if ( connect_type == "on_load" ) connect ( signal_name_t, slot_name_t );
	}
}
void SceneObject::disconnect_signals()
{
	SignalName signal_name_t = _scene_name_ + "->reinit";
	SlotName slot_name_t = _scene_name_ + "->" + _object_name_ + "->on_scene_reinit";
	disconnect (signal_name_t, slot_name_t);
	
	///@TODO вернуть auto на место
	std::vector<SignalConnection>::iterator it;
	for ( it = _signal_connections_.begin(); it != _signal_connections_.end(); ++it )
	{
		disconnect ( it->signal_name, it->slot_name );
	}
}

void SceneObject::connect_signals()
{
	for ( std::vector<SignalConnection>::iterator it = _signal_connections_.begin(); it != _signal_connections_.end(); ++it )
	{
		connect ( it->signal_name, it->slot_name );
	}
}
void SceneObject::register_slots()
{
	register_slot ( _scene_name_ + "->" + _object_name_ + "->" + "on_activate", &_on_activate );
	register_slot ( _scene_name_ + "->" + _object_name_ + "->" + "on_deactivate", &_on_deactivate );
	register_slot ( _scene_name_ + "->" + _object_name_ + "->" + "on_key_press", &_on_key_press );
	register_slot ( _scene_name_ + "->" + _object_name_ + "->" + "on_key_release", &_on_key_release );
	register_slot ( _scene_name_ + "->" + _object_name_ + "->" + "on_character", &_on_character );
	register_slot ( _scene_name_ + "->" + _object_name_ + "->" + "on_mouse_release", &_on_mouse_release );
	register_slot ( _scene_name_ + "->" + _object_name_ + "->" + "on_scene_reinit", &_on_scene_reinit );
	
	SignalName signal_name_t = _scene_name_ + "->reinit";
	SlotName slot_name_t = _scene_name_ + "->" + _object_name_ + "->on_scene_reinit";
	connect (signal_name_t, slot_name_t);

}

void SceneObject::unregister_slots()
{
	unregister_slot ( _scene_name_ + "->" + _object_name_ + "->" + "on_activate" );
	unregister_slot ( _scene_name_ + "->" + _object_name_ + "->" + "on_deactivate" );
	unregister_slot ( _scene_name_ + "->" + _object_name_ + "->" + "on_key_press" );
	unregister_slot ( _scene_name_ + "->" + _object_name_ + "->" + "on_key_release" );
	unregister_slot ( _scene_name_ + "->" + _object_name_ + "->" + "on_character" );
	unregister_slot ( _scene_name_ + "->" + _object_name_ + "->" + "on_mouse_release" );
	unregister_slot ( _scene_name_ + "->" + _object_name_ + "->" + "on_scene_reinit" );
	SignalName signal_name_t = _scene_name_ + "->reinit";
	SlotName slot_name_t = _scene_name_ + "->" + _object_name_ + "->on_scene_reinit";
	disconnect (signal_name_t, slot_name_t);
}
