// Aseprite
// Copyright (C) 2019-2020  Igara Studio S.A.
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.

#ifndef APP_CLOSED_DOCS_H_INCLUDED
#define APP_CLOSED_DOCS_H_INCLUDED
#pragma once

#include "base/time.h"

#include <atomic>
#include <condition_variable>
#include <mutex>
#include <thread>
#include <vector>

namespace app {

class Doc;
class Preferences;

// Handle the list of closed docs:
// * When a document is closed, we keep it for some time so the user
//   can undo the close command without losing the undo history.
// * For the first closed document, a thread is launched to wait
//   until we can definitely delete the doc after X minutes (like a
//   garbage collector).
// * If the document was not restore, we delete it from memory, if
//   the document was restore, we remove it from the m_docs.
class ClosedDocs {
public:
  ClosedDocs(const Preferences& pref);
  ~ClosedDocs();

  bool hasClosedDocs();
  void addClosedDoc(Doc* doc);
  Doc* reopenLastClosedDoc();

  // Called at the very end to get all closed docs, remove them from
  // the list of closed docs, and stop the thread.
  std::vector<Doc*> getAndRemoveAllClosedDocs();

private:
  void backgroundThread();

  struct ClosedDoc {
    Doc* doc;
    base::tick_t timestamp;
  };

  std::atomic<bool> m_done;
  base::tick_t m_dataRecoveryPeriodMSecs;
  base::tick_t m_keepClosedDocAliveForMSecs;
  std::vector<ClosedDoc> m_docs;
  std::mutex m_mutex;
  std::condition_variable m_cv;
  std::thread m_thread;
};

} // namespace app

#endif
