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

%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-

-module(nouveau_util).

-include("nouveau.hrl").
-include_lib("couch/include/couch_db.hrl").

-export([
    index_name/1,
    design_doc_to_indexes/2,
    design_doc_to_index/3,
    active_sigs/1,
    active_sigs/2,
    verify_index_exists/2,
    ensure_local_purge_docs/2,
    maybe_create_local_purge_doc/2,
    get_local_purge_doc_id/1,
    get_local_purge_doc_body/3,
    nouveau_url/0
]).

index_name(Path) when is_binary(Path) ->
    <<(node_prefix())/binary, "/", Path/binary>>;
index_name(#index{} = Index) ->
    <<(node_prefix())/binary, "/", (Index#index.dbname)/binary, "/", (Index#index.sig)/binary>>.

node_prefix() ->
    atom_to_binary(node(), utf8).

%% copied from dreyfus_index.erl
design_doc_to_indexes(DbName, #doc{body = {Fields}} = Doc) ->
    RawIndexes = couch_util:get_value(<<"nouveau">>, Fields, {[]}),
    case RawIndexes of
        {IndexList} when is_list(IndexList) ->
            {IndexNames, _} = lists:unzip(IndexList),
            lists:flatmap(
                fun(IndexName) ->
                    case (catch design_doc_to_index(DbName, Doc, IndexName)) of
                        {ok, #index{} = Index} -> [Index];
                        _ -> []
                    end
                end,
                IndexNames
            );
        _ ->
            []
    end.

%% copied from dreyfus_index.erl
design_doc_to_index(DbName, #doc{id = Id, body = {Fields}}, IndexName) ->
    Language = couch_util:get_value(<<"language">>, Fields, <<"javascript">>),
    {RawIndexes} = couch_util:get_value(<<"nouveau">>, Fields, {[]}),
    InvalidDDocError =
        {invalid_design_doc, <<"index `", IndexName/binary, "` must have parameter `index`">>},
    case lists:keyfind(IndexName, 1, RawIndexes) of
        false ->
            {error, {not_found, <<IndexName/binary, " not found.">>}};
        {IndexName, {Index}} ->
            DefaultAnalyzer = couch_util:get_value(<<"default_analyzer">>, Index, <<"standard">>),
            FieldAnalyzers = couch_util:get_value(<<"field_analyzers">>, Index, #{}),
            case couch_util:get_value(<<"index">>, Index) of
                undefined ->
                    {error, InvalidDDocError};
                Def ->
                    Sig = ?l2b(
                        couch_util:to_hex(
                            crypto:hash(
                                sha256,
                                ?term_to_bin(
                                    {DefaultAnalyzer, FieldAnalyzers, Def}
                                )
                            )
                        )
                    ),
                    {ok, #index{
                        dbname = DbName,
                        default_analyzer = DefaultAnalyzer,
                        field_analyzers = FieldAnalyzers,
                        ddoc_id = Id,
                        def = Def,
                        def_lang = Language,
                        name = IndexName,
                        sig = Sig
                    }}
            end;
        _ ->
            {error, InvalidDDocError}
    end.

active_sigs(DbName) when is_binary(DbName) ->
    couch_util:with_db(DbName, fun active_sigs/1);
active_sigs(Db) ->
    DbName = couch_db:name(Db),
    {ok, DesignDocs} = couch_db:get_design_docs(Db),
    lists:usort(
        lists:flatmap(
            fun(Doc) -> active_sigs(DbName, Doc) end,
            [couch_doc:from_json_obj(DD) || DD <- DesignDocs]
        )
    ).

active_sigs(DbName, #doc{} = Doc) ->
    Indexes = design_doc_to_indexes(DbName, Doc),
    lists:map(fun(Index) -> Index#index.sig end, Indexes).

verify_index_exists(DbName, Props) ->
    try
        Type = couch_util:get_value(<<"type">>, Props),
        if
            Type =/= <<"nouveau">> ->
                false;
            true ->
                DDocId = couch_util:get_value(<<"ddoc_id">>, Props),
                IndexName = couch_util:get_value(<<"indexname">>, Props),
                Sig = couch_util:get_value(<<"signature">>, Props),
                couch_util:with_db(DbName, fun(Db) ->
                    case couch_db:get_design_doc(Db, DDocId) of
                        {ok, #doc{} = DDoc} ->
                            {ok, IdxState} = design_doc_to_index(
                                DbName, DDoc, IndexName
                            ),
                            IdxState#index.sig == Sig;
                        {not_found, _} ->
                            false
                    end
                end)
        end
    catch
        _:_ ->
            false
    end.

ensure_local_purge_docs(DbName, DDocs) ->
    couch_util:with_db(DbName, fun(Db) ->
        lists:foreach(
            fun(DDoc) ->
                #doc{body = {Props}} = DDoc,
                case couch_util:get_value(<<"indexes">>, Props) of
                    undefined ->
                        false;
                    _ ->
                        try design_doc_to_indexes(DbName, DDoc) of
                            SIndexes -> ensure_local_purge_doc(Db, SIndexes)
                        catch
                            _:_ ->
                                ok
                        end
                end
            end,
            DDocs
        )
    end).

ensure_local_purge_doc(Db, SIndexes) ->
    if
        SIndexes =/= [] ->
            lists:map(
                fun(SIndex) ->
                    maybe_create_local_purge_doc(Db, SIndex)
                end,
                SIndexes
            );
        true ->
            ok
    end.

maybe_create_local_purge_doc(Db, Index) ->
    DocId = get_local_purge_doc_id(Index#index.sig),
    case couch_db:open_doc(Db, DocId) of
        {ok, _Doc} ->
            ok;
        {not_found, _} ->
            DbPurgeSeq = couch_db:get_purge_seq(Db),
            DocContent = get_local_purge_doc_body(
                DocId, DbPurgeSeq, Index
            ),
            couch_db:update_doc(Db, DocContent, [])
    end.

get_local_purge_doc_id(Sig) ->
    iolist_to_binary([?LOCAL_DOC_PREFIX, "purge-", "nouveau-", Sig]).

get_local_purge_doc_body(LocalDocId, PurgeSeq, Index) ->
    #index{
        name = IdxName,
        ddoc_id = DDocId,
        sig = Sig
    } = Index,
    NowSecs = os:system_time(second),
    JsonList =
        {[
            {<<"_id">>, LocalDocId},
            {<<"purge_seq">>, PurgeSeq},
            {<<"updated_on">>, NowSecs},
            {<<"indexname">>, IdxName},
            {<<"ddoc_id">>, DDocId},
            {<<"signature">>, Sig},
            {<<"type">>, <<"nouveau">>}
        ]},
    couch_doc:from_json_obj(JsonList).

nouveau_url() ->
    config:get("nouveau", "url", "http://127.0.0.1:8080").
