/******************************************************************************
 *
 * Project:  OpenCPN
 * Authors:  David Register
 *           Sean D'Epagnier
 *
 ***************************************************************************
 *   Copyright (C) 2016 by David S. Register                               *
 *                                                                         *
 *   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 Street, Fifth Floor, Boston, MA 02110-1301,  USA.         *
 ***************************************************************************
 */

#ifndef __GLTEXTUREMANAGER_H__
#define __GLTEXTUREMANAGER_H__

const wxEventType wxEVT_OCPN_COMPRESSIONTHREAD = wxNewEventType();

class JobTicket;
class wxGenericProgressDialog;

WX_DECLARE_LIST(JobTicket, JobList);

class ProgressInfoItem;
WX_DECLARE_LIST(ProgressInfoItem, ProgressInfoList);

class ProgressInfoItem
{
public:
    ProgressInfoItem(){};
    ~ProgressInfoItem(){};
    
    wxString file_path;
    wxString msgx;
};



class CompressionPoolThread : public wxThread
{
public:
    CompressionPoolThread(JobTicket *ticket, wxEvtHandler *message_target);
    void *Entry();
    
    wxEvtHandler        *m_pMessageTarget;
    JobTicket           *m_ticket;
};



class OCPN_CompressionThreadEvent: public wxEvent
{
public:
    OCPN_CompressionThreadEvent( wxEventType commandType = wxEVT_NULL, int id = 0 );
    ~OCPN_CompressionThreadEvent( );
    
    // accessors
    void SetTicket( JobTicket *ticket ){m_ticket = ticket;}
    JobTicket *GetTicket(void){ return m_ticket; }
    
    // required for sending with wxPostEvent()
    wxEvent *Clone() const;

    int        type;
    int        nstat;
    int        nstat_max;
    
private:
    JobTicket  * m_ticket;
};

class CompressionPoolThread;
class JobTicket
{
public:
    JobTicket();
    ~JobTicket() { free(level0_bits); }
    bool DoJob();
    bool DoJob(const wxRect &rect);
    
    glTexFactory *pFact;
    wxRect      m_rect;
    int         level_min_request;
    int         ident;
    bool        b_throttle;
    
    CompressionPoolThread *pthread;
    unsigned char *level0_bits;
    unsigned char *comp_bits_array[10];
    wxString    m_ChartPath;
    bool        b_abort;
    bool        b_isaborted;
    bool        bpost_zip_compress;
    bool        binplace;
    unsigned char *compcomp_bits_array[10];
    int         compcomp_size_array[10];
    bool        b_inCompressAll;
};


//      This is a hashmap with Chart full path as key, and glTexFactory as value
WX_DECLARE_STRING_HASH_MAP( glTexFactory*, ChartPathHashTexfactType );

//      glTextureManager Definition
class glTextureManager : public wxEvtHandler
{
public:
    glTextureManager();
    ~glTextureManager();

    void OnEvtThread( OCPN_CompressionThreadEvent & event );
    void OnTimer(wxTimerEvent &event);
    bool ScheduleJob( glTexFactory *client, const wxRect &rect, int level_min,
                      bool b_throttle_thread, bool b_nolimit, bool b_postZip, bool b_inplace);

    int GetRunningJobCount(){ return running_list.GetCount(); }
    int GetJobCount(){ return GetRunningJobCount() + todo_list.GetCount(); }
    bool AsJob( wxString const &chart_path ) const;
    void PurgeJobList( wxString chart_path = wxEmptyString );
    void ClearJobList();
    void ClearAllRasterTextures(void);
    bool PurgeChartTextures(ChartBase *pc, bool b_purge_factory = false);
    bool TextureCrunch(double factor);
    bool FactoryCrunch(double factor);
    void BuildCompressedCache();
    
    //    This is a hash table
    //    key is Chart full path
    //    Value is glTexFactory*
    ChartPathHashTexfactType   m_chart_texfactory_hash;

private:    
    bool DoJob( JobTicket *pticket );
    bool DoThreadJob(JobTicket* pticket);
    bool StartTopJob();
    
    JobList             running_list;
    JobList             todo_list;
    int                 m_max_jobs;

    int		m_prevMemUsed;

    wxTimer     m_timer;
    size_t      m_ticks;
    wxGenericProgressDialog *m_progDialog;
    wxString    m_progMsg;
    unsigned int  m_jcnt;
    ProgressInfoList    progList;
    bool        m_skip;
    bool        m_skipout;
    bool        m_bcompact;
};

class glTextureDescriptor;
void GetFullMap( glTextureDescriptor *ptd,  const wxRect &rect, wxString chart_path, int level);
int TextureDim(int level);
int TextureTileSize(int level, bool compressed);

#endif
