%% =====================================================================
%% Refactoring: Import
%% =====================================================================

-module(refac2_Import).

-export([refac_Import/1, refac_Import_eclipse/1]).

-include("../include/wrangler.hrl").

-spec(refac_Import/1::(filename()) -> 
	     {error, string()} | {question, string()} |{ok, [filename()], boolean()}).
refac_Import(FileName) ->
    refac_Import(FileName,emacs).

-spec(refac_Import_eclipse/1::(filename()) ->
	     {error, string()} | {question, string()} | {warning, string()} |
		 {ok, [{filename(), filename(), string()}]}).
refac_Import_eclipse(FileName) ->
    refac_Import(FileName,eclipse).


refac_Import(FileName,Editor) ->

	{ok,X} = smerl:for_file(FileName),
	Forms=smerl:get_forms(X),
    Imports=getImports(Forms),
	NX2=deleteImports(Forms),
	NXX = smerl:set_forms(X,lists:reverse(applyRefacImportsFun(NX2,Imports))),
	smerl:to_src(NXX,FileName),
	{ok,[]}.

	
getImports([])->[];
getImports([{attribute,_,import,{Mod,Funcs}}|Attributes]) ->
	[{Mod,Funcs}|getImports(Attributes)];
getImports([_|Attributes]) ->
	getImports(Attributes).

deleteImports([])->[];
deleteImports([{attribute,_,import,_}|Attributes]) ->
	deleteImports(Attributes);
deleteImports([Head|Attributes])->
	[Head|deleteImports(Attributes)].


findImport(_,[]) -> false;
findImport(Func,[{Mod,Functions}|Modules])-> 
	case lists:member(Func,Functions) of
		true -> {ok,Mod};
		false -> findImport(Func,Modules)
	end.


applyRefacImportsFun([],_)->[];
applyRefacImportsFun([{function,LINE,Name,Arity,Clauses}|Funs],Imports) ->
	NewClauses = applyRefac_clausesGeneric(Clauses,Imports),
	[{function,LINE,Name,Arity,NewClauses}|applyRefacImportsFun(Funs,Imports)];
applyRefacImportsFun(Other,_)->
	Other.


applyRefac_clausesGeneric([],_) -> [];
applyRefac_clausesGeneric([{clause,LINE,Patterns,Guards,Body}|Clauses],Imports)->
	NBody = applyRefac_expressionsGeneric(Body,Imports),
	NPatterns = applyRefac_expressionsGeneric(Patterns,Imports),
	NGuards = applyRefac_expressionsGeneric(Guards,Imports),
	[{clause,LINE,NPatterns,NGuards,NBody}|applyRefac_clausesGeneric(Clauses,Imports)];
applyRefac_clausesGeneric(Other,_)->
	Other.


applyRefac_expressionsGeneric([],_)->[];
applyRefac_expressionsGeneric([Exp|Exps],Imports)->
	[applyRefac_expressionGeneric(Exp,Imports)|applyRefac_expressionsGeneric(Exps,Imports)];
applyRefac_expressionsGeneric(Other,Imports)->
	applyRefac_expressionGeneric(Other,Imports).


applyRefac_expressionGeneric({match,LINE,E1,E2},Imports)->
	{match,LINE,applyRefac_expressionsGeneric(E1,Imports),
	 applyRefac_expressionsGeneric(E2,Imports)};
applyRefac_expressionGeneric({tuple,LINE,Exps},Imports)->
	{tuple,LINE,applyRefac_expressionsGeneric(Exps,Imports)};
applyRefac_expressionGeneric({cons,LINE,E1,E2},Imports)->
	{cons,LINE,applyRefac_expressionsGeneric(E1,Imports),
	 applyRefac_expressionsGeneric(E2,Imports)};


%****************************************************************************
	
	
applyRefac_expressionGeneric({op,LINE,Op,E1,E2},Imports)->
	{op,LINE,Op,applyRefac_expressionsGeneric(E1,Imports),
	 applyRefac_expressionsGeneric(E2,Imports)};
applyRefac_expressionGeneric({op,LINE,Op,E},Imports)->
	{op,LINE,Op,applyRefac_expressionsGeneric(E,Imports)};

applyRefac_expressionGeneric({record,LINE,Name,RecordFields},Imports)->
	{record,LINE,Name,applyRefac_expressionsGeneric(RecordFields,Imports)};
applyRefac_expressionGeneric({record,LINE,E0,Name,RecordFields},Imports)->
	{record,LINE,applyRefac_expressionsGeneric(E0,Imports),Name,applyRefac_expressionsGeneric(RecordFields,Imports)};
applyRefac_expressionGeneric({record_index,LINE,Name,Field},Imports)->
	{record_index,LINE,Name,applyRefac_expressionsGeneric(Field,Imports)};
applyRefac_expressionGeneric({record_field,LINE,E0,Field},Imports)->
	{record_field,LINE,applyRefac_expressionsGeneric(E0,Imports),applyRefac_expressionsGeneric(Field,Imports)};
applyRefac_expressionGeneric({record_field,LINE,E0,Name,Field},Imports)->
	{record_field,LINE,applyRefac_expressionsGeneric(E0,Imports),Name,applyRefac_expressionsGeneric(Field,Imports)};

applyRefac_expressionGeneric({'catch',LINE,E},Imports)->
	{'catch',LINE,applyRefac_expressionsGeneric(E,Imports)};


%****************************************************************************
applyRefac_expressionGeneric({call,LINE,{remote,LINE,EM,EF},Exps},Imports)->
	{call,LINE,{remote,LINE,applyRefac_expressionsGeneric(EM,Imports),
	 applyRefac_expressionsGeneric(EF,Imports)},
	 applyRefac_expressionsGeneric(Exps,Imports)};
applyRefac_expressionGeneric({call,LINE,EF,Exps},Imports)->
	{Var,_,Func}=EF,
	case findImport({Func,length(Exps)},Imports) of
		{ok,Module} -> {call,LINE,{remote,LINE,{Var,LINE,Module},
									 applyRefac_expressionGeneric(EF,Imports)},
						  			 applyRefac_expressionsGeneric(Exps,Imports)};
		false ->  		{call,LINE,applyRefac_expressionsGeneric(EF,Imports),
	 					applyRefac_expressionsGeneric(Exps,Imports)}
	end;
%****************************************************************************
	

applyRefac_expressionGeneric({block,LINE,E},Imports)->
	{block,LINE,applyRefac_expressionsGeneric(E,Imports)};
applyRefac_expressionGeneric({'if',LINE,Clasues},Imports)->
	{'if',LINE,applyRefac_clausesGeneric(Clasues,Imports)};
applyRefac_expressionGeneric({'case',LINE,E,Clasues},Imports)->
	{'case',LINE,applyRefac_expressionGeneric(E,Imports),
	applyRefac_clausesGeneric(Clasues,Imports)};
applyRefac_expressionGeneric({lc,LINE,E0,W},Imports)->
	{lc,LINE,applyRefac_expressionsGeneric(E0,Imports),applyRefac_expressionsGeneric(W,Imports)};
applyRefac_expressionGeneric({bc,LINE,E0,W},Imports)->
	{bc,LINE,applyRefac_expressionsGeneric(E0,Imports),applyRefac_expressionsGeneric(W,Imports)};

applyRefac_expressionGeneric({'try',LINE,B,[],[],A},Imports)->
	{'try',LINE,applyRefac_expressionsGeneric(B,Imports),[],[],applyRefac_expressionsGeneric(A,Imports)};
applyRefac_expressionGeneric({'try',LINE,B,[],C,[]},Imports)->
	{'try',LINE,applyRefac_expressionsGeneric(B,Imports),[],applyRefac_expressionsGeneric(C,Imports),[]};
applyRefac_expressionGeneric({'try',LINE,B,C,[],A},Imports)->
	{'try',LINE,applyRefac_expressionsGeneric(B,Imports),applyRefac_expressionsGeneric(C,Imports),[],applyRefac_expressionsGeneric(A,Imports)};
applyRefac_expressionGeneric({'try',LINE,B,[],C,A},Imports)->
	{'try',LINE,applyRefac_expressionsGeneric(B,Imports),[],applyRefac_expressionsGeneric(C,Imports),applyRefac_expressionsGeneric(A,Imports)};
applyRefac_expressionGeneric({'try',LINE,B,C,T,[]},Imports)->
	{'try',LINE,applyRefac_expressionsGeneric(B,Imports),applyRefac_expressionsGeneric(C,Imports),applyRefac_expressionsGeneric(T,Imports),[]};
applyRefac_expressionGeneric({'try',LINE,B,C,T,A},Imports)->
	{'try',LINE,applyRefac_expressionsGeneric(B,Imports),applyRefac_expressionsGeneric(C,Imports),applyRefac_expressionsGeneric(T,Imports),applyRefac_expressionGeneric(A,Imports)};

applyRefac_expressionGeneric({'fun',LINE,F},Imports)->
	{'fun',LINE,applyRefac_expressionsGeneric(F,Imports)};
applyRefac_expressionGeneric({'query',LINE,F},Imports)->
	{'query',LINE,applyRefac_expressionsGeneric(F,Imports)};
applyRefac_expressionGeneric({'receive',LINE,C},Imports)->
	{'receive',LINE,applyRefac_clausesGeneric(C,Imports)};
applyRefac_expressionGeneric({'receive',LINE,C,E,B},Imports)->
	{'receive',LINE,applyRefac_clausesGeneric(C,Imports),applyRefac_expressionsGeneric(E,Imports),applyRefac_expressionsGeneric(B,Imports)};
applyRefac_expressionGeneric({generate,LINE,P,E},Imports)->
	{generate,LINE,applyRefac_expressionsGeneric(P,Imports),applyRefac_expressionsGeneric(E,Imports)};
applyRefac_expressionGeneric({b_generate,LINE,P,E},Imports)->
	{b_generate,LINE,applyRefac_expressionsGeneric(P,Imports),applyRefac_expressionsGeneric(E,Imports)};

applyRefac_expressionGeneric({clauses,Clauses},Imports)->
	{clauses,applyRefac_clausesGeneric(Clauses,Imports)};

%Casos dels clause
applyRefac_expressionGeneric([A|B],Imports) ->
	[applyRefac_expressionGeneric(A,Imports)|applyRefac_expressionsGeneric(B,Imports)];

applyRefac_expressionGeneric(Other,_)->
	Other.