%%% Copyright (c) 2007- Facebook
%%% Distributed under the Thrift Software License
%%% 
%%% See accompanying file LICENSE or visit the Thrift site at:
%%% http://developers.facebook.com/thrift/

-module(oop).

-export([get/2, set/3, call/2, call/3, inspect/1, start_new/2, is_object/1, class/1]).
-export([behaviour_info/1]).

-include("thrift.hrl").
-include("oop.hrl").

%%%
%%% behavior definition
%%%

behaviour_info(callbacks) -> 
    [ 
      {attr, 4}, 
      {super, 0} 
    ];
behaviour_info(_) -> 
    undefined.

%%

-define(TRIED, lists:reverse([TryModule|TriedRev])).

%% no super attr defined
-define(NOSUPEROBJ, exit({missing_attr_super, {inspect(Obj), ?TRIED}})).

-define(NOMETHOD, exit({missing_method, {Method, inspect(Obj), tl(Args), ?TRIED}})).

-define(NOATTR, exit({missing_attr, {hd(tl(Args)), inspect(FirstObj), ?TRIED}})).

-define(NOATTR_SET, exit({missing_attr, {Field, inspect(Obj), ".." %% TODO: give a backtrace
			}})).


%%% get(Obj, Field) -> term()
%%% looks up Field in Obj or its ancestor objects

get(Obj, Field) ->
    call(Obj, attr, [get, Field, get]).

set(Obj, Field, Value) -> %% TODO: could be tail-recursive
    Module = ?CLASS(Obj),
    try
	Module:attr(Obj, set, Field, Value)
    catch
	error:Kind when Kind == undef; Kind == function_clause ->
	    case get_superobject(Obj) of
		{ ok, Superobj } ->
		    Super1 = set(Superobj, Field, Value),
		    try
			Module:attr(Obj, set, super, Super1)
		    catch %% TODO(cpiro): remove check
			X -> exit({burnsauce, X})
		    end;
		none ->
		    ?NOATTR_SET
	    end
    end.
    

%%% C++                   <-> Erlang
%%% classes                   modules
%%%   class b : public a        a:super() -> b.
%%%   

get_superobject(Obj) ->
    try
	{ok, (?CLASS(Obj)):attr(Obj, get, super, get)}
    catch
	error:Kind when Kind == undef; Kind == function_clause ->
	    none
    end.

is_object(Obj) when is_tuple(Obj) ->
    try
	(?CLASS(Obj)):super(), %% if it's an object its first element will be a class name, and it'll have super/0
	true
    catch
	error:Kind when Kind == undef; Kind == function_clause ->
	    false
    end;
is_object(_) ->
    false.

call(Obj, Method, ArgsProper) ->
    %% error_logger:info_msg("call called: Obj=~p Method=~p ArgsProper=~p", [inspect(Obj), Method, ArgsProper]),
    Args = [Obj|ArgsProper], %% prepend This to args
    TryModule = ?CLASS(Obj),
    call_loop(Obj, Method, Args, TryModule, [], Obj).

call(Obj, Method) -> 
    call(Obj, Method, []).

call_loop(Obj, Method, Args, TryModule, TriedRev, FirstObj) ->
    try
	%% error_logger:info_msg("call_loop~n ~p~n ~p~n ~p~n ~p", [inspect(Obj), Method, Args, TryModule]),
	apply(TryModule, Method, Args)
    catch
	error:Kind when Kind == undef; Kind == function_clause ->
	    case { TryModule:super(), Method } of 
		{ none, attr } ->
		    ?NOATTR;
		
		{ none, _ } -> 
		    ?NOMETHOD;
		
		{ Superclass, attr } -> 
		    %% look for attrs in the "super object"
		    
		    case get_superobject(Obj) of
			{ok, Superobj} when (TryModule == ?CLASS(Obj)) -> 
			    %% replace This with Superobj
			    NewArgs = [Superobj|tl(Args)], 
			    call_loop(Superobj, Method, NewArgs, 
				      Superclass, [TryModule|TriedRev], FirstObj);
			
			{ok, _Superobj} -> % failed guard TODO(cpiro): removeme
			    exit(oh_noes);
			
			none    -> ?NOSUPEROBJ
		    end;
		
		{ SuperClass, _ } ->
		    call_loop(Obj, Method, Args, 
			      SuperClass, [TryModule|TriedRev], FirstObj)
	    end
    end.
    
class(Obj) when is_tuple(Obj) ->
    case is_object(Obj) of
	true ->
	    ?CLASS(Obj);
	false ->
	    none
    end;
class(_) ->
    none.

%% careful: not robust against records beginning with a class name
%% (note: we can't just guard with is_record(?CLASS(Obj), Obj) since we
%% can't/really really shouldn't require all record definitions in this file
inspect(Obj) ->
    try
	case is_object(Obj) of
	    true ->
		DeepList = inspect_loop(Obj, "#<"),
		lists:flatten(DeepList);
	    false ->
		thrift_utils:sformat("~p", [Obj])
	end
    catch
	_:E ->
	    thrift_utils:sformat("INSPECT_ERROR(~p) ~p", [E, Obj])

	    %% TODO(cpiro): bring this back once we're done testing:
	    %% _:E -> thrift_utils:sformat("~p", [Obj])
    end.

inspect_loop(Obj, Str) ->
    Class   = ?CLASS(Obj),
    Inspect = Class:inspect(Obj),
    Current = atom_to_list(Class) ++ ": " ++ Inspect,

    case get_superobject(Obj) of
	{ ok, Superobj } ->
	    inspect_loop(Superobj, Str ++ Current ++ " | ");
	none ->
	    Str ++ Current ++ ">"
    end.

%% TODO: voids take only ok as return? 
start_new(none=Resv, _) ->
    error_logger:format("can't instantiate ~p: class name is a reserved word", [Resv]),
    error;
start_new(Class, Args) ->
    {ok, Pid} = gen_server:start_link(thrift_oop_server, {Class, Args}, []),
    Pid.
