/******************************************************************************
 * $Id: chartdldr_pi.h,v 1.0 2011/02/26 01:54:37 nohal Exp $
 *
 * Project:  OpenCPN
 * Purpose:  Chart Downloader Plugin
 * Author:   Pavel Kalian
 *
 ***************************************************************************
 *   Copyright (C) 2011 by Pavel Kalian                                    *
 *   $EMAIL$                                                               *
 *                                                                         *
 *   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.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************
 */

#ifndef _CHARTDLDRPI_H_
#define _CHARTDLDRPI_H_

#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif  // precompiled headers

#include <wx/fileconf.h>
#include <wx/tokenzr.h>
#include <wx/event.h>

#include <wx/imaglist.h>

#include <map>

#include "version.h"

#define MY_API_VERSION_MAJOR 1
#define MY_API_VERSION_MINOR 13

#define USERDATA "{USERDATA}"

#include "ocpn_plugin.h"

#include "chartdldrgui.h"
#include "chartcatalog.h"

#define UPDATE_DATA_FILENAME "chartdldr_pi.dat"

// forward declarations
class ChartSource;
class ChartDldrPanelImpl;
class ChartDldrGuiAddSourceDlg;
class ChartDldrPrefsDlgImpl;

//----------------------------------------------------------------------------------------------------------
//    The PlugIn Class Definition
//----------------------------------------------------------------------------------------------------------

class chartdldr_pi : public opencpn_plugin_113 {
public:
  chartdldr_pi(void* ppimgr);

  //    The required PlugIn Methods
  int Init(void);
  bool DeInit(void);

  int GetAPIVersionMajor();
  int GetAPIVersionMinor();
  int GetPlugInVersionMajor();
  int GetPlugInVersionMinor();
  wxBitmap* GetPlugInBitmap();
  wxString GetCommonName();
  wxString GetShortDescription();
  wxString GetLongDescription();

  void OnSetupOptions(void);
  void OnCloseToolboxPanel(int page_sel, int ok_apply_cancel);

  //    The required override PlugIn Methods
  void ShowPreferencesDialog(wxWindow* parent);

  //    Other public methods
  bool SaveConfig(void);
  bool ProcessFile(const wxString& aFile, const wxString& aTargetDir,
                   bool aStripPath = true,
                   wxDateTime aMTime = wxDateTime::Now());
  bool ExtractZipFiles(const wxString& aZipFile, const wxString& aTargetDir,
                       bool aStripPath = true,
                       wxDateTime aMTime = wxDateTime::Now(),
                       bool aRemoveZip = false);
#ifdef DLDR_USE_LIBARCHIVE
  bool ExtractLibArchiveFiles(const wxString& aArchiveFile,
                              const wxString& aTargetDir,
                              bool aStripPath = true,
                              wxDateTime aMTime = wxDateTime::Now(),
                              bool aRemoveArchive = false);
#endif
#if defined(CHARTDLDR_RAR_UNARR) || !defined(DLDR_USE_LIBARCHIVE)
  bool ExtractUnarrFiles(const wxString& aRarFile, const wxString& aTargetDir,
                         bool aStripPath = true,
                         wxDateTime aMTime = wxDateTime::Now(),
                         bool aRemoveRar = false);
#endif

  void UpdatePrefs(ChartDldrPrefsDlgImpl* dialog);

  //    Public properties
  std::vector<std::unique_ptr<ChartSource>> m_ChartSources;
  wxWindow* m_parent_window;
  ChartCatalog m_pChartCatalog;
  ChartSource* m_pChartSource;
  void SetSourceId(int id) { m_selected_source = id; }
  int GetSourceId() { return m_selected_source; }
  wxString GetBaseChartDir() { return m_base_chart_dir; }
  bool m_preselect_new;
  bool m_preselect_updated;
  bool m_allow_bulk_update;

private:
  wxFileConfig* m_pconfig;
  wxScrolledWindow* m_pOptionsPage;
  bool LoadConfig(void);

  wxString m_schartdldr_sources;
  int m_selected_source;

  ChartDldrPanelImpl* m_dldrpanel;
  wxString m_base_chart_dir;
};

class ChartSource : public wxTreeItemData {
public:
  ChartSource(wxString name, wxString url, wxString localdir);
  ~ChartSource();

  wxString GetName() { return m_name; }
  wxString GetUrl() { return m_url; }
  wxString GetDir() { return m_dir; }
  void SetDir(wxString dir) { m_dir = dir; }
  void SetName(wxString name) { m_name = name; }
  void SetUrl(wxString url) { m_url = url; }
  bool ExistsLocaly(wxString chart_number, wxString filename);
  bool IsNewerThanLocal(wxString chart_number, wxString filename,
                        wxDateTime validDate);
  void UpdateLocalFiles() { GetLocalFiles(); }

  bool UpdateDataExists();
  void LoadUpdateData();
  void SaveUpdateData();
  void ChartUpdated(wxString chart_number, time_t timestamp);

private:
  wxArrayString m_localfiles;
  std::vector<wxDateTime> m_localdt;
  void GetLocalFiles();
  wxString m_name;
  wxString m_url;
  wxString m_dir;
  std::map<std::string, time_t> m_update_data;
};

/** Implementing ChartDldrPanel */
class ChartDldrPanelImpl : public ChartDldrPanel {
  friend class chartdldr_pi;

private:
  bool DownloadChart(wxString url, wxString file, wxString title);
  int to_download;

  int updatingAll;
  bool cancelled;
  bool DownloadIsCancel;
  chartdldr_pi* pPlugIn;
  bool m_populated;

  void OnPopupClick(wxCommandEvent& evt);
  int GetSelectedCatalog();
  void AppendCatalog(std::unique_ptr<ChartSource>& cs);
  void DoEditSource();

  bool m_bTransferComplete;
  bool m_bTransferSuccess;
  long m_totalsize;
  long m_transferredsize;
  int m_failed_downloads;
  int m_downloading;

  void DisableForDownload(bool enabled);
  bool m_bconnected;
  bool m_bInfoHold;  // Don't update chart selection stats right now
  size_t m_newCharts;
  size_t m_updatedCharts;

protected:
  // Handlers for ChartDldrPanel events.
  void SetSource(int id);
  void SelectSource(wxListEvent& event) override;
  void AddSource(wxCommandEvent& event) override;
  void DeleteSource(wxCommandEvent& event) override;
  void EditSource(wxCommandEvent& event) override;
  void UpdateChartList(wxCommandEvent& event) override;
  void OnDownloadCharts(wxCommandEvent& event) override;

  void OnSelectChartItem(wxCommandEvent& event);
  void OnSelectNewCharts(wxCommandEvent& event);
  void OnSelectUpdatedCharts(wxCommandEvent& event);
  void OnSelectAllCharts(wxCommandEvent& event);

  void DownloadCharts();
  void DoHelp(wxCommandEvent& event) override {
#ifdef __WXMSW__
    wxLaunchDefaultBrowser(_T("file:///") + *GetpSharedDataLocation() +
                           _T("plugins/chartdldr_pi/data/doc/index.html"));
#else
    wxLaunchDefaultBrowser(_T("file://") + *GetpSharedDataLocation() +
                           _T("plugins/chartdldr_pi/data/doc/index.html"));
#endif
  }
  void UpdateAllCharts(wxCommandEvent& event) override;
  void OnShowLocalDir(wxCommandEvent& event) override;
  void OnPaint(wxPaintEvent& event) override;
  void OnLeftDClick(wxMouseEvent& event) override;

  void CleanForm();
  void FillFromFile(wxString url, wxString dir, bool selnew = false,
                    bool selupd = false);

  void OnContextMenu(wxMouseEvent& event) override;
  void SetBulkUpdate(bool bulk_update);

  int GetChartCount();
  int GetCheckedChartCount();
  bool isChartChecked(int i);
  void CheckAllCharts(bool value);
  void InvertCheckAllCharts();

  void CheckNewCharts(bool value);
  void CheckUpdatedCharts(bool value);

public:
  // ChartDldrPanelImpl() { m_bconnected = false; DownloadIsCancel = false; }
  ~ChartDldrPanelImpl();
  ChartDldrPanelImpl(chartdldr_pi* plugin = NULL, wxWindow* parent = NULL,
                     wxWindowID id = wxID_ANY,
                     const wxPoint& pos = wxDefaultPosition,
                     const wxSize& size = wxDefaultSize,
                     long style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
  void SelectCatalog(int item);
  void onDLEvent(OCPN_downloadEvent& ev);
  void CancelDownload() {
    Disconnect(
        wxEVT_DOWNLOAD_EVENT,
        (wxObjectEventFunction)(wxEventFunction)&ChartDldrPanelImpl::onDLEvent);
    cancelled = true;
    m_bconnected = false;
  }

private:
  DECLARE_EVENT_TABLE()
};

class ChartDldrGuiAddSourceDlg : public AddSourceDlg {
protected:
  void OnChangeType(wxCommandEvent& event);
  void OnSourceSelected(wxTreeEvent& event);
  void OnOkClick(wxCommandEvent& event);
  void OnCancelClick(wxCommandEvent& event);

  bool LoadSources();
  bool LoadSections(const wxTreeItemId& root, pugi::xml_node& node);
  bool LoadSection(const wxTreeItemId& root, pugi::xml_node& node);
  bool LoadCatalogs(const wxTreeItemId& root, pugi::xml_node& node);
  bool LoadCatalog(const wxTreeItemId& root, pugi::xml_node& node);

public:
  ChartDldrGuiAddSourceDlg(wxWindow* parent);
  ~ChartDldrGuiAddSourceDlg();
  void SetBasePath(const wxString path) { m_base_path = path; }
  void SetSourceEdit(std::unique_ptr<ChartSource>& cs);

private:
  bool ValidateUrl(const wxString Url, bool catalog_xml = true);
  wxString FixPath(wxString path);
  wxString m_base_path;
  wxString m_last_path;
  wxImageList* p_iconList;
#ifdef __OCPN__ANDROID__
  wxImageList* p_buttonIconList;
#endif /* __OCPN__ANDROID__ */
};

class ChartDldrPrefsDlgImpl : public ChartDldrPrefsDlg {
protected:
  void OnOkClick(wxCommandEvent& event);

public:
  ChartDldrPrefsDlgImpl(wxWindow* parent);
  ~ChartDldrPrefsDlgImpl();
  wxString GetPath() { return m_tcDefaultDir->GetValue(); }
  void SetPath(const wxString path);
  void GetPreferences(bool& preselect_new, bool& preselect_updated,
                      bool& bulk_update);
  void SetPreferences(bool preselect_new, bool preselect_updated,
                      bool bulk_update);
};

#endif
