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

#ifndef APP_THUMBNAIL_GENERATOR_H_INCLUDED
#define APP_THUMBNAIL_GENERATOR_H_INCLUDED
#pragma once

#include "base/concurrent_queue.h"

#include <memory>
#include <mutex>
#include <vector>

namespace base {
  class thread;
}

namespace app {
  class FileOp;
  class IFileItem;

  class ThumbnailGenerator {
    ThumbnailGenerator();
  public:
    static ThumbnailGenerator* instance();

    // Generate a thumbnail for the given file-item.  It must be called
    // from the GUI thread.
    void generateThumbnail(IFileItem* fileitem);

    // Checks the status of workers. If there are workers that already
    // done its job, we've to destroy them. This function must be called
    // from the GUI thread (because a thread is joint to it).
    // Returns true if there are workers generating thumbnails.
    bool checkWorkers();

    // Stops all workers generating thumbnails. This is an non-blocking
    // operation. The cancelation of all workers is done in a background
    // thread.
    void stopAllWorkers();

  private:
    void startWorker();

    class Worker;
    using WorkerPtr = std::unique_ptr<Worker>;
    using WorkerList = std::vector<WorkerPtr>;

    struct Item {
      IFileItem* fileitem;
      FileOp* fop;
      Item() : fileitem(nullptr), fop(nullptr) { }
      Item(const Item& item) : fileitem(item.fileitem), fop(item.fop) { }
      Item(IFileItem* fileitem, FileOp* fop)
        : fileitem(fileitem), fop(fop) {
      }
    };

    int m_maxWorkers;
    WorkerList m_workers;
    std::mutex m_workersAccess;
    base::concurrent_queue<Item> m_remainingItems;
  };

} // namespace app

#endif
