/*
 This file is part of GNU Taler
 (C) 2019 GNUnet e.V.

 GNU Taler is free software; you can redistribute it and/or modify it under the
 terms of the GNU General Public License as published by the Free Software
 Foundation; either version 3, or (at your option) any later version.

 GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

 You should have received a copy of the GNU General Public License along with
 GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */

/**
 * Imports.
 */
import {
  AttentionInfo,
  Logger,
  TalerPreciseTimestamp,
  UserAttentionByIdRequest,
  UserAttentionPriority,
  UserAttentionUnreadList,
  UserAttentionsCountResponse,
  UserAttentionsRequest,
  UserAttentionsResponse,
} from "@gnu-taler/taler-util";
import { timestampPreciseFromDb, timestampPreciseToDb } from "./db.js";
import { WalletExecutionContext } from "./wallet.js";

const logger = new Logger("operations/attention.ts");

export async function getUserAttentionsUnreadCount(
  wex: WalletExecutionContext,
  req: UserAttentionsRequest,
): Promise<UserAttentionsCountResponse> {
  const total = await wex.db.runReadOnlyTx(
    { storeNames: ["userAttention"] },
    async (tx) => {
      let count = 0;
      await tx.userAttention.iter().forEach((x) => {
        if (
          req.priority !== undefined &&
          UserAttentionPriority[x.info.type] !== req.priority
        )
          return;
        if (x.read !== undefined) return;
        count++;
      });

      return count;
    },
  );

  return { total };
}

export async function getUserAttentions(
  wex: WalletExecutionContext,
  req: UserAttentionsRequest,
): Promise<UserAttentionsResponse> {
  return await wex.db.runReadOnlyTx(
    { storeNames: ["userAttention"] },
    async (tx) => {
      const pending: UserAttentionUnreadList = [];
      await tx.userAttention.iter().forEach((x) => {
        if (
          req.priority !== undefined &&
          UserAttentionPriority[x.info.type] !== req.priority
        )
          return;
        pending.push({
          info: x.info,
          when: timestampPreciseFromDb(x.created),
          read: x.read !== undefined,
        });
      });

      return { pending };
    },
  );
}

export async function markAttentionRequestAsRead(
  wex: WalletExecutionContext,
  req: UserAttentionByIdRequest,
): Promise<void> {
  await wex.db.runReadWriteTx({ storeNames: ["userAttention"] }, async (tx) => {
    const ua = await tx.userAttention.get([req.entityId, req.type]);
    if (!ua) throw Error("attention request not found");
    tx.userAttention.put({
      ...ua,
      read: timestampPreciseToDb(TalerPreciseTimestamp.now()),
    });
  });
}

/**
 * the wallet need the user attention to complete a task
 * internal API
 *
 * @param wex
 * @param info
 */
export async function addAttentionRequest(
  wex: WalletExecutionContext,
  info: AttentionInfo,
  entityId: string,
): Promise<void> {
  await wex.db.runReadWriteTx({ storeNames: ["userAttention"] }, async (tx) => {
    await tx.userAttention.put({
      info,
      entityId,
      created: timestampPreciseToDb(TalerPreciseTimestamp.now()),
      read: undefined,
    });
  });
}

/**
 * user completed the task, attention request is not needed
 * internal API
 *
 * @param wex
 * @param created
 */
export async function removeAttentionRequest(
  wex: WalletExecutionContext,
  req: UserAttentionByIdRequest,
): Promise<void> {
  await wex.db.runReadWriteTx({ storeNames: ["userAttention"] }, async (tx) => {
    const ua = await tx.userAttention.get([req.entityId, req.type]);
    if (!ua) throw Error("attention request not found");
    await tx.userAttention.delete([req.entityId, req.type]);
  });
}
