//
// meam.hpp
//
// LGPL Version 2.1 HEADER START
//
// 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 2.1 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
//
// LGPL Version 2.1 HEADER END
//

//
// Copyright (c) 2020--2021, Regents of the University of Minnesota.
// All rights reserved.
//
// Contributors:
//    Yaser Afshar
//

#ifndef MEAM_HPP
#define MEAM_HPP

#include <memory>

#include "KIM_ModelDriverHeaders.hpp"

extern "C" {
int ModelDriverCreateRoutine(
    KIM::ModelDriverCreate *const model_driver_create,
    KIM::LengthUnit const requested_length_unitit,
    KIM::EnergyUnit const requested_energy_unit,
    KIM::ChargeUnit const requested_charge_unitit,
    KIM::TemperatureUnit const requested_temperature_unit,
    KIM::TimeUnit const requested_time_unitit);
}

// Forward declaration
class MEAMImplementation;

/*!
 * \brief MEAM model driver class for %KIM API
 *
 *
 * \note
 * There is no need to make these "extern" since KIM will only access them
 * via function pointers.  "static" is required so that there is not
 * n implicit this pointer added to the prototype by the C++ compiler
 */
class MEAM {
 public:
  /*!
   * \brief Construct a new MEAM object
   *
   * \param model_driver_create
   * \param requested_length_unitit
   * \param requested_energy_unit
   * \param requested_charge_unitit
   * \param requested_temperature_unit
   * \param requested_time_unitit
   * \param ierr
   */
  MEAM(KIM::ModelDriverCreate *const model_driver_create,
       KIM::LengthUnit const requested_length_unitit,
       KIM::EnergyUnit const requested_energy_unit,
       KIM::ChargeUnit const requested_charge_unitit,
       KIM::TemperatureUnit const requested_temperature_unit,
       KIM::TimeUnit const requested_time_unitit, int *const ierr);

  /*!
   * \brief Destroy the MEAM object
   *
   */
  ~MEAM() = default;

  static int Destroy(KIM::ModelDestroy *const model_destroy);

  static int Refresh(KIM::ModelRefresh *const model_refresh);

  static int WriteParameterizedModel(
      KIM::ModelWriteParameterizedModel const
          *const model_write_parameterized_model);

  static int Compute(
      KIM::ModelCompute const *const model_compute,
      KIM::ModelComputeArguments const *const model_compute_arguments);

  static int ComputeArgumentsCreate(
      KIM::ModelCompute const *const model_compute,
      KIM::ModelComputeArgumentsCreate
          *const model_compute_arguments_createate);

  static int ComputeArgumentsDestroy(
      KIM::ModelCompute const *const model_compute,
      KIM::ModelComputeArgumentsDestroy *const model_compute_arguments_destroy);

 private:
  std::unique_ptr<MEAMImplementation> meam_implementation_;
};

#endif  // MEAM_HPP
