//------------------------------------------------------------------------------
// This file is part of the OpenStructure project <www.openstructure.org>
//
// Copyright (C) 2008-2020 by the OpenStructure authors
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 3.0 of the License, or (at your option)
// any later version.
// This library 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 Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this library; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//------------------------------------------------------------------------------
#ifndef OST_CONOP_CHEMDICT_PARSER_HH
#define OST_CONOP_CHEMDICT_PARSER_HH

/*
  Author: Marco Biasini
 */
 
 
#include <ost/mol/chem_class.hh>
#include <ost/mol/chem_type.hh>
#include <ost/io/mol/star_parser.hh>
#include <ost/conop/compound_lib.hh>
 
namespace ost { namespace io {

typedef enum {
  ATOM_SPEC,
  BOND_SPEC,
  DESC_SPEC,
  DONT_KNOW
} LoopType;

class DLLEXPORT_OST_IO ChemdictParser : public StarParser {
public:
  ChemdictParser(std::istream& stream, conop::Compound::Dialect dialect,
    bool ignore_reserved=false, bool ignore_obsolete=false):
    StarParser(stream), compound_(new conop::Compound("UNK")), 
    last_(0), loop_type_(DONT_KNOW), dialect_(dialect),
    ignore_reserved_(ignore_reserved), ignore_obsolete_(ignore_obsolete),
    imported_count_(0)
  {
    this->InitTypeMap();
    this->InitPDBXTypeMap();
  }

  virtual bool OnBeginData(const StringRef& data_name);

  virtual bool OnBeginLoop(const StarLoopDesc& header);

  virtual void OnDataRow(const StarLoopDesc& header, 
                         const std::vector<StringRef>& columns);

  virtual void OnDataItem(const StarDataItem& item);

  virtual void OnEndData();

  void SetCompoundLib(const conop::CompoundLibPtr& lib) 
  {
    lib_=lib;
  }

  /// \brief Get the number of compounds that were successfully parsed
  int GetImportedCount()
  {
    return imported_count_;
  }
private:
  void InitTypeMap();  
  void InitPDBXTypeMap();
  bool IsNameReserved(const String& data_name);
  conop::CompoundLibPtr                   lib_;
  conop::CompoundPtr                      compound_;
  bool                                    valid_compound_;
  typedef enum {
    ATOM_NAME=0,
    ALT_ATOM_NAME=1,
    IS_AROMATIC=2,
    ORDINAL=3,
    IS_LEAVING=4,
    ELE=5,
    CHARGE=6,
    ATOM_ID1=0,
    ATOM_ID2=1,
    BOND_ORDER=2,
    DESC_TYPE=0,
    DESC=1,
    PROGRAM=2,
  } PropIndex;
  char                                    last_;
  int                                     indices_[10];
  static std::map<String, mol::ChemClass> tm_;
  static std::map<String, mol::ChemType>  xtm_;
  std::map<String, int>                   atom_map_;
  LoopType                                loop_type_;  
  conop::AtomSpec                         atom_;
  bool                                    valid_atom_;
  conop::Compound::Dialect                dialect_;
  bool                                    ignore_reserved_;
  bool                                    ignore_obsolete_;
  int                                     imported_count_;
};


}}


#endif
