/***************************************************************************
 *
 * Project:  OpenCPN
 *
 ***************************************************************************
 *   Copyright (C) 2015 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.         *
 ***************************************************************************
 */

#include <wx/log.h>
#include <wx/tokenzr.h>
#include <wx/textfile.h>
#include <wx/filename.h>

#include "config.h"

#include "s57RegistrarMgr.h"
#include "S57ClassRegistrar.h"

extern S57ClassRegistrar* g_poRegistrar;

static int s57_initialize(const wxString& csv_dir, FILE* flog) {
  //      Get one instance of the s57classregistrar,
  //      And be prepared to give it to any module that needs it

  if (g_poRegistrar == NULL) {
    g_poRegistrar = new S57ClassRegistrar();

    if (!g_poRegistrar->LoadInfo(csv_dir.mb_str(), FALSE)) {
      wxString msg(_T("   Error: Could not load S57 ClassInfo from "));
      msg.Append(csv_dir);
      wxLogMessage(msg);

      delete g_poRegistrar;
      g_poRegistrar = NULL;
    }
  }

  return 0;
}

s57RegistrarMgr::s57RegistrarMgr(const wxString& csv_dir, FILE* flog) {
  s57_initialize(csv_dir, flog);

  //  Create and initialize the S57 Attribute helpers
  s57_attr_init(csv_dir);
  //  Create and initialize the S57 Feature code helpers
  s57_feature_init(csv_dir);
}

s57RegistrarMgr::~s57RegistrarMgr() {
  delete g_poRegistrar;
  g_poRegistrar = NULL;
}

bool s57RegistrarMgr::s57_attr_init(const wxString& csv_dir) {
  //  Find, open, and read the file {csv_dir}/s57attributes.csv
  wxString csv_t = csv_dir;
  wxChar sep = wxFileName::GetPathSeparator();
  if (csv_t.Last() != sep) csv_t.Append(sep);

  wxTextFile tFile;
  wxString targetFile = csv_t + _T("s57attributes.csv");

  if (!tFile.Open(targetFile)) {
    wxString msg(_T("   Error: Could not load S57 Attribute Info from "));
    msg.Append(csv_dir);
    wxLogMessage(msg);

    return false;
  }

  //  populate the member hashmaps

  // First map: Key is char[] attribute acronym, value is standard ID
  // Second map: Key is standard ID, value is char[] attribute acronym

  wxString str;
  for (str = tFile.GetFirstLine(); !tFile.Eof(); str = tFile.GetNextLine()) {
    wxStringTokenizer tk(str, _T(","));

    wxString ident = tk.GetNextToken();
    long nID = -1;
    if (ident.ToLong(&nID)) {
      wxString description = tk.GetNextToken();
      wxString acronym = tk.GetNextToken();

      m_attrHash1[acronym] = nID;
      m_attrHash2[nID] = acronym.c_str();
    }
  }

  return true;
}

bool s57RegistrarMgr::s57_feature_init(const wxString& csv_dir) {
  //  Find, open, and read the file {csv_dir}/s57objectclasses.csv
  wxString csv_t = csv_dir;
  wxChar sep = wxFileName::GetPathSeparator();
  if (csv_t.Last() != sep) csv_t.Append(sep);

  wxTextFile tFile;
  wxString targetFile = csv_t + _T("s57objectclasses.csv");

  if (!tFile.Open(targetFile)) {
    wxString msg(_T("   Error: Could not load S57 Feature Info from "));
    msg.Append(csv_dir);
    wxLogMessage(msg);

    return false;
  }

  //  populate the member hashmaps

  // First map: Key is char[] feature acronym, value is standard ID
  // Second map: Key is standard ID, value is char[] feature acronym

  wxString str;
  for (str = tFile.GetFirstLine(); !tFile.Eof(); str = tFile.GetNextLine()) {
    wxStringTokenizer tk(str, _T(","));

    wxString ident = tk.GetNextToken();
    long nID = -1;
    //         if( ident.ToLong( &nID )){
    //             wxString description = tk.GetNextToken();
    //             wxString acronym = tk.GetNextToken();
    //
    //             m_featureHash1[acronym] = nID;
    //             m_featureHash2[nID] = acronym.c_str();
    //
    //         }
    if (ident.ToLong(&nID)) {
      wxString description = tk.GetNextToken();
      //            wxString d2;
      while (!description.EndsWith("\"")) description += tk.GetNextToken();

      wxString acronym = tk.GetNextToken();

      m_featureHash1[acronym] = nID;
      m_featureHash2[nID] = acronym.c_str();
    }
  }

  return true;
}

int s57RegistrarMgr::getAttributeID(const char* pAttrName) {
  wxString key(pAttrName);

  if (m_attrHash1.find(key) == m_attrHash1.end())
    return -1;
  else
    return m_attrHash1[key];
}

std::string s57RegistrarMgr::getAttributeAcronym(int nID) {
  if (m_attrHash2.find(nID) == m_attrHash2.end())
    return "";
  else
    return m_attrHash2[nID];
}

std::string s57RegistrarMgr::getFeatureAcronym(int nID) {
  if (m_featureHash2.find(nID) == m_featureHash2.end())
    return "";
  else
    return m_featureHash2[nID];
}
