%%--------------------------------------------------------------------
%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%%     http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% %CopyrightEnd%
%%
%%-----------------------------------------------------------------
%% File: otp_man_index.erl
%% 
%% Description:
%%    This file generates the module overview in the documentation.
%%
%%-----------------------------------------------------------------

-module(otp_man_index). 

-export([gen/1, gen/2]).
-include_lib("kernel/include/file.hrl").


gen([Source, RootDir, OutFile])  when is_atom(RootDir),  is_atom(OutFile)->
    gen(Source, RootDir, OutFile).

gen(RootDir, OutFile) ->
    gen(rel, RootDir, OutFile).

gen(Source, RootDir, OutFile) ->
    Bases = [{"../lib/", filename:join(RootDir, "lib")},
	     {"../", RootDir}],
    Apps = find_application_paths(Source, Bases),
    RefPages = find_ref_files(Apps),
    gen_html(RefPages, atom_to_list(OutFile)).
    

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Find Reference files
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

find_ref_files(Apps) ->
    find_ref_files(Apps, []).

find_ref_files([], Acc) ->
    Acc;
find_ref_files([{App, Vsn, AppPath, RelPath} |Apps], Acc) ->
    case filelib:wildcard(filename:join(AppPath, "*.html")) of
	[] ->
	    find_ref_files(Apps, Acc);
	Result ->

	    Refs1 = lists:filter(fun(Ref) -> 
				      case file:read_file(Ref) of
					  {ok, Bin} ->
					     case re:run(Bin, ".*<!-- refpage -->.*",[]) of
						 {match, _} ->
						     true;
						 nomatch ->
						     false
					     end;
					 {error, Reason} ->
					      exit(io_lib:format("~p : ~s\n", [Reason, Ref]))
				      end  
			      end,
			      Result),

	    Refs2 = lists:map(fun(Ref) -> 
				      Module = filename:basename(Ref, ".html"),
				      {string:to_lower(Module),
				      Module,
				      App ++ "-" ++ Vsn,
				      RelPath, 
				      filename:join(RelPath, filename:basename(Ref))}
			     end,
			     Refs1),
	    find_ref_files(Apps, Refs2 ++ Acc)
    end.

find_application_paths(_, []) ->
    [];
find_application_paths(Source, [{URL, Dir} | Paths]) ->

    AppDirs = get_app_dirs(Dir),
    AppPaths = get_app_paths(Source, AppDirs, URL),
    AppPaths ++ find_application_paths(Source, Paths).

get_app_paths(src, AppDirs, URL) ->
    Sub1 = "doc/html",
    lists:map(
      fun({App, AppPath}) -> 
	      VsnFile = filename:join(AppPath, "vsn.mk"),
	      VsnStr = 
		  case file:read_file(VsnFile) of
		      {ok, Bin} ->
			  case re:run(Bin, ".*VSN\s*=\s*([0-9\.]+).*",[{capture,[1],list}]) of
			      {match, [V]} ->
				  V;
			      nomatch ->
				  exit(io_lib:format("No VSN variable found in ~s\n",
						     [VsnFile]))
			  end;
		      {error, Reason} ->
			  exit(io_lib:format("~p : ~s\n", [Reason, VsnFile]))
		  end,
	      AppURL = URL ++ App ++ "-" ++ VsnStr,
	      {App, VsnStr, AppPath ++ "/" ++ Sub1, AppURL ++ "/" ++ Sub1}
      end, AppDirs);
get_app_paths(rel, AppDirs, URL) ->
    Sub1 = "doc/html",
    lists:map(
      fun({App, AppPath}) -> 
	      [AppName, VsnStr] = string:tokens(App, "-"),
	      AppURL = URL ++ App,
	      {AppName, VsnStr, AppPath ++ "/" ++ Sub1, AppURL ++ "/" ++ Sub1}
      end, AppDirs).

    
get_app_dirs(Dir) ->
    {ok, Files} = file:list_dir(Dir),
    AFiles = 
	lists:map(fun(File) -> {File, filename:join([Dir, File])} end, Files),
    lists:zf(fun is_app_with_doc/1, AFiles).

is_app_with_doc({"." ++ _ADir, _APath}) ->
    false;
is_app_with_doc({ADir, APath}) ->
    case file:read_file_info(filename:join([APath, "info"])) of
	{ok, _FileInfo} ->
	    {true, {ADir, APath}};
	_ ->
	    false
    end.




gen_html(RefPages, OutFile)->
    case file:open(OutFile, [write]) of
	{ok, Out} ->
	    io:fwrite(Out, "~s\n", [html_header()]),

	    SortedPages = lists:sort(RefPages),
	    
	    lists:foreach(fun({_,Module, App, AppDocDir, RefPagePath}) -> 
				  io:fwrite(Out, "  <tr>\n",[]),
				  io:fwrite(Out, "    <td><a href=\"~s\">~s</a></td>\n", 
					    [RefPagePath, Module]),
				  io:fwrite(Out, "    <td><a HREF=\"~s\">~s</a></td>\n", 
					    [filename:join(AppDocDir, "index.html"), 
					     App]),
				  io:fwrite(Out, "  </TR>\n",[])
			  end, 
			  SortedPages),
	    
	    {Year, _, _} = date(),
	    io:fwrite(Out, "~s\n", [html_footer(integer_to_list(Year))]);
	{error, Reason} ->
	    exit("~p: ~s\n",[Reason, OutFile])
    end.
	  


html_header() ->
    "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"
	"<!-- This file was generated by the otp_man_index  -->\n"
	"<html>\n"
	"<head>\n"
	"  <link rel=\"stylesheet\" href=\"otp_doc.css\" type=\"text/css\"/>\n"
	"  <title>Erlang/OTP Manual Page Index</title>\n"
	"</head>\n"
	"<body>\n"
	"<center>\n"
	"<!-- A HREF=\"http://www.erlang.org/\">\n"
	"<img alt=\"Erlang logo\" src=\"erlang-logo.png\"/>\n"
	"</a><br -->\n"
	"<small>\n"
	"[ <A HREF=\"index.html\">Up</A> | <A HREF=\"http://www.erlang.org/\">Homepage</A> ]\n"
	"</small><br>\n"
	"<h1>OTP Reference Page Index</h1>\n"
	"</center>\n"
	"<center>\n"
	"<table class=\"man-index\">\n"
	"<tr>\n"
	"  <th>Manual Page</th><th>Application</th>\n"
	"</tr>\n".



html_footer(Year) ->
    "</table>\n"
	"</center>\n"
	"<p/>\n"
	"<center>\n"
	"<hr/>\n"
	"<small>\n"
	"Copyright &copy; 1991-" ++ Year ++ "\n"
	"<a href=\"http://www.ericsson.com/technology/opensource/erlang/\">\n"
	"Ericsson AB</a>\n"
	"</small>\n"
	"</center>\n"
	"</body>\n"
	"</html>\n".
