% 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.

-module(couch_stats_httpd).
-include_lib("couch/include/couch_db.hrl").

-export([handle_stats_req/1]).

%% exported for use by chttpd_misc
-export([transform_stats/1, nest/1, to_ejson/1, extract_path/2]).

handle_stats_req(#httpd{method='GET', path_parts=[_ | Path]}=Req) ->
    flush(Req),
    Stats0 = couch_stats:fetch(),
    Stats = transform_stats(Stats0),
    Nested = nest(Stats),
    EJSON0 = to_ejson(Nested),
    EJSON1 = extract_path(Path, EJSON0),
    couch_httpd:send_json(Req, EJSON1).


transform_stats(Stats) ->
    transform_stats(Stats, []).

transform_stats([], Acc) ->
    Acc;
transform_stats([{Key, Props} | Rest], Acc) ->
    {_, Type} = proplists:lookup(type, Props),
    transform_stats(Rest, [{Key, transform_stat(Type, Props)} | Acc]).


transform_stat(counter, Props) ->
    Props;
transform_stat(gauge, Props) ->
    Props;
transform_stat(histogram, Props) ->
    lists:map(fun
        ({value, Value}) ->
            {value, lists:map(fun
                ({Key, List}) when Key == percentile; Key == histogram ->
                    {Key, [tuple_to_list(Item) || Item <- List]};
                (Else) ->
                    Else
            end, Value)};
        (Else) ->
            Else
      end, Props).


nest(Proplist) ->
    nest(Proplist, []).

nest([], Acc) ->
    Acc;
nest([{[Key|Keys], Value}|Rest], Acc) ->
    Acc1 = case proplists:lookup(Key, Acc) of
        {Key, Old} ->
            [{Key, nest([{Keys, Value}], Old)}|proplists:delete(Key, Acc)];
        none ->
            Term = lists:foldr(fun(K, A) -> [{K, A}] end, Value, Keys),
            [{Key, Term}|Acc]
    end,
    nest(Rest, Acc1).


to_ejson([{_, _}|_]=Proplist) ->
    EJSONProps = lists:map(
       fun({Key, Value}) -> {maybe_format_key(Key), to_ejson(Value)} end,
       Proplist
    ),
    {EJSONProps};
to_ejson(NotAProplist) ->
    NotAProplist.


extract_path([], EJSON) ->
    EJSON;
extract_path([Key | Rest], {Props}) ->
    case proplists:lookup(Key, Props) of
        {Key, SubEJSON} ->
            extract_path(Rest, SubEJSON);
        none ->
            null
    end;
extract_path([_ | _], _NotAnObject) ->
    null.


maybe_format_key(Key) when is_list(Key) ->
    list_to_binary(Key);
maybe_format_key(Key) when is_atom(Key) ->
    list_to_binary(atom_to_list(Key));
maybe_format_key(Key) when is_integer(Key) ->
    list_to_binary(integer_to_list(Key));
maybe_format_key(Key) when is_binary(Key) ->
    Key.

flush(Req) ->
    case couch_util:get_value("flush", chttpd:qs(Req)) of
        "true" ->
            couch_stats_aggregator:flush();
        _Else ->
            ok
    end.
