/* nm_filetype_thread.hh
 * This file belongs to Worker, a file manager for UN*X/X11.
 * Copyright (C) 2011,2013 Ralf Hoffmann.
 * You can contact me at: ralf@boomerangsworld.de
 *   or http://www.boomerangsworld.de/worker
 *
 * This program 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 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#ifndef NM_FILETYPE_THREAD_HH
#define NM_FILETYPE_THREAD_HH

#include <wdefines.h>
#include "aguix/thread.hh"
#include "aguix/condvar.h"
#include <memory>
#include <list>
#include "fileentry_customcolor.hh"
#include "condparser.h"

class List;
class Worker;
class WCFiletype;
class WConfig;

class NM_Filetype_Thread : public Thread
{
public:
    NM_Filetype_Thread();
    ~NM_Filetype_Thread();

    void setWorker( Worker *worker );

    int run();

    typedef enum { THREAD_RUN,
                   THREAD_EXIT,
                   THREAD_STOP } thread_order_t;

    int switchOrder( thread_order_t neworder );

    typedef struct check_entry {
        check_entry() : pos( -1 ),
                        dont_check_content( false ) {}
        std::string fullname;
        int pos;
        bool dont_check_content;
    } check_entry_t;

    class check_filetype_result {
    public:
        check_entry_t entry;
        std::vector<unsigned int> ft_index;
        FileEntryCustomColor custom_color;
        std::string filetype_file_output;
        std::string mime_type;
    };

    void putRequest( const check_entry_t &req );
    void clearRequests();

    void result_list_clear();
    void result_list_lock();
    void result_list_unlock();
    check_filetype_result result_list_remove_locked();
    bool result_list_is_empty_locked();

    void copy_filetypes( List *filetypes );
    void clear_filetypes();

    // only for master thread
    static WCFiletype *findFiletype( WConfig *wconfig,
                                     const std::vector<unsigned int> &v );
private:

    // fifo for ft-results
    // main thread does remove
    // slave does put
    // no size limitation
    class result_list {
    public:
        result_list();
        ~result_list();
        result_list( const result_list &other );
        result_list &operator=( const result_list &other );

        bool isEmpty_locked();
        int put_locked( check_filetype_result elem );
        check_filetype_result remove_locked();
    
        void lock();
        void unlock();
    protected:
        std::list< check_filetype_result > entries;
        MutEx ex;
    };

    int slave_checkFiletype( const check_entry_t &entry,
                             check_filetype_result &res_return );
    int switchStatus( thread_order_t newstatus );

    Worker *m_worker;

    CondParser condparser;

    int m_running;

    CondVar m_ordervar_cv;
    thread_order_t m_order;
    CondVar m_statusvar_cv;
    thread_order_t m_status;

    std::list< check_entry_t > m_entries_to_check;
    result_list m_result_list;

    struct {
        List *filetypes;
        MutEx filetype_ex;
    } m_filetype_copy;
};

#endif
