/* BEGIN software license
 *
 * MsXpertSuite - mass spectrometry software suite
 * -----------------------------------------------
 * Copyright(C) 2009,...,2026 Filippo Rusconi
 *
 * http://www.msxpertsuite.org
 *
 * This file is part of the MsXpertSuite project.
 *
 * The MsXpertSuite project is the successor of the massXpert project. This
 * project now includes various independent modules:
 *
 * - MassXpert, model polymer chemistries and simulate mass spectrometric data;
 * - MineXpert, a powerful TIC chromatogram/mass spectrum viewer/miner;
 *
 * 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 3 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, see <http://www.gnu.org/licenses/>.
 *
 * END software license
 */

#pragma once


/////////////////////// stdlib includes


/////////////////////// Qt includes


/////////////////////// pappsomspp includes


/////////////////////// libXpertMass includes

#include <MsXpS/libXpertMassCore/PolChemDef.hpp>

/////////////////////// libXpertMassGui includes


/////////////////////// Local includes

#include "ui_CalculatorWnd.h"
#include "AbstractMainTaskWindow.hpp"
#include "CalculatorRecorderDlg.hpp"
#include "CalculatorChemPadDlg.hpp"


namespace MsXpS
{
namespace MassXpert
{


enum class FormulaComboAction : uint8_t
{
  ADD = 0x000,
  REMOVE,
  CLEAR,
  SIMPLIFY
};


enum class FormulaHandling : uint8_t
{
  IMMEDIATE        = 1 << 0,
  PRINT            = 1 << 1,
  WITH_SPACE       = 1 << 2,
  PRINT_WITH_SPACE = (PRINT | WITH_SPACE),
};


// Overload bitwise OR operator
inline FormulaHandling
operator|(FormulaHandling lhs, FormulaHandling rhs)
{
  return static_cast<FormulaHandling>(
    static_cast<std::underlying_type_t<FormulaHandling>>(lhs) |
    static_cast<std::underlying_type_t<FormulaHandling>>(rhs));
}

// Overload bitwise AND operator
inline FormulaHandling
operator&(FormulaHandling lhs, FormulaHandling rhs)
{
  return static_cast<FormulaHandling>(
    static_cast<std::underlying_type_t<FormulaHandling>>(lhs) &
    static_cast<std::underlying_type_t<FormulaHandling>>(rhs));
}

// Overload bitwise XOR operator
inline FormulaHandling
operator^(FormulaHandling lhs, FormulaHandling rhs)
{
  return static_cast<FormulaHandling>(
    static_cast<std::underlying_type_t<FormulaHandling>>(lhs) ^
    static_cast<std::underlying_type_t<FormulaHandling>>(rhs));
}

// Overload bitwise NOT operator
inline FormulaHandling
operator~(FormulaHandling opt)
{
  return static_cast<FormulaHandling>(
    ~static_cast<std::underlying_type_t<FormulaHandling>>(opt));
}

// Overload bitwise OR assignment operator
inline FormulaHandling &
operator|=(FormulaHandling &lhs, FormulaHandling rhs)
{
  lhs = lhs | rhs;
  return lhs;
}

// Overload bitwise AND assignment operator
inline FormulaHandling &
operator&=(FormulaHandling &lhs, FormulaHandling rhs)
{
  lhs = lhs & rhs;
  return lhs;
}


class CalculatorWnd : public AbstractMainTaskWindow
{
  Q_OBJECT

  public:
  CalculatorWnd(ProgramWindow *parent,
                const QString &polChemDefFilePath,
                const QString &application_name,
                const QString &description,
                const QString &mono,
                const QString &avg);

  ~CalculatorWnd();

  bool m_forciblyClose              = false;
  FormulaHandling m_formulaHandling = FormulaHandling::IMMEDIATE;


  libXpertMassCore::PolChemDefCstSPtr polChemDef();
  QString polChemDefName();

  void updateWindowTitle();
  bool populatePolChemDefComboBoxes();

  bool setupChemicalPad();

  void recordResult();
  void updateSeedResultLineEdits();

  void recorderDlgClosed();
  void chemPadDlgClosed();

  int accountFormula(const QString & = QString(""), double = 1);
  int accountMonomer();
  int accountModif();
  int accountSequence();

  void setFormulaHandling(FormulaHandling formula_handling);

  void addFormulaToMemory();
  void removeFormulaFromMemory();
  void clearWholeMemory();
  QString simplifyFormula();

  public slots:
  void addToResult();
  void sendToResult();
  void removeFromResult();
  void clearSeed();
  void addToSeed();
  void sendToSeed();
  void removeFromSeed();
  void clearResult();
  void showRecorder(int);

  void formulaActionsComboBoxActivated(int formula_combo_action);

  void showChemPad(int);

  void apply(const QString & = QString(""));

  void mzCalculation();
  void isotopicPatternCalculation();
  void decimalPlacesOptions();

  protected:
  Ui::CalculatorWnd m_ui;

  int decimals      = 4;
  double m_seedMono = 0.0;
  double m_seedAvg  = 0.0;

  double m_tempMono = 0.0;
  double m_tempAvg  = 0.0;

  double m_resultMono = 0.0;
  double m_resultAvg  = 0.0;

  CalculatorRecorderDlg *mpa_recorderDlg = 0;
  CalculatorChemPadDlg *mpa_chemPadDlg   = 0;

  libXpertMassCore::PolChemDefSPtr msp_polChemDef;

  void readSettings();
  void writeSettings();

  bool initialize();

  void closeEvent(QCloseEvent *event);
};


} // namespace MassXpert
} // namespace MsXpS
