/*
 * Copyright (c) 2026 University of Insubria <https://www.uninsubria.it>
 *
 * 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. All we ask is that proper credit is given
 * for our work, which includes - but is not limited to - adding the above
 * copyright notice to the beginning of your source code files, and to any
 * copyright notice that you may distribute with programs based on this work.
 *
 * 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 program; if not, write to the Free Software Foundation, Inc.
 * <https://fsf.org/>
 */

package qsardes.descriptor.qsarme;

import java.util.List;
import java.util.Map;
import org.openscience.cdk.interfaces.IAtom;
import qsardes.descriptor.DescriptorElectrTopolStateIndex;
import qsardes.molecule.Molecule;

/**
 * Electrotopological state index descriptors (QSAR-ME Profiler 2025).
 * <BR><BR>
 * Calculates electrotopological state index descriptors.
 * <BR><BR>
 * Returns
 * <BR><BR>
 * sumI - Sum of the intrinsic states.
 * <BR>
 * meanI - Mean intrinsic states.
 * <BR>
 * hmax - Maximum H E-State.
 * <BR>
 * gmax - Maximum E-State.
 * <BR>
 * hmin - Minimum H E-State.
 * <BR>
 * gmin - Minimum E-State.
 * <BR>
 * LipoaffinityIndex - Lipoaffinity index.
 * <BR>
 * MAXDN - Molecule maximum negative intrinsic state difference related to the
 * nucleophilicity of the molecule.
 * <BR>
 * MAXDP - Molecule maximum positive intrinsic state difference related to the
 * electrophilicity of the molecule.
 * <BR>
 * MAXDN2 - Molecule maximum negative intrinsic state difference related to the
 * nucleophilicity of the molecule.
 * <BR>
 * MAXDP2 - Molecule maximum positive intrinsic state difference related to the
 * electrophilicity of the molecule.
 * <BR>
 * DELS - Molecule sum of all atoms intrinsic state (Molconn-Z definition)
 * differences.
 * <BR>
 * DELS2 - Molecule sum of all atoms intrinsic state (Kier-Hall definition)
 * differences.
 * <BR><BR>
 * #sLi, #ssBe, #ssssBem, #ssBH, #sssB, #ssssBm, #sCH3, #dCH2, #ssCH2, #tCH,
 * #dsCH, #aaCH, #sssCH, #ddC, #tsC, #dssC, #aasC, #aaaC, #ssssC, #sNH3p,
 * #sNH2, #ssNH2p, #dNH, #ssNH, #aaNH, #tN, #sssNHp, #dsN, #aaN, #sssN, #ddsN,
 * #aasN, #ssssNp, #sOH, #dO, #ssO, #aaO, #sF, #sSiH3, #ssSiH2, #sssSiH,
 * #ssssSi, #sPH2, #ssPH, #sssP, #dsssP, #sssssP, #sSH, #dS, #ssS, #aaS, #dssS,
 * #ddssS, #sCl, #sGeH3, #ssGeH2, #sssGeH, #ssssGe, #sAsH2, #ssAsH, #sssAs,
 * #dsssAs, #sssssAs, #sSeH, #dSe, #ssSe, #aaSe, #dssSe, #ddssSe, #sBr,
 * #sSnH3, #ssSnH2, #sssSnH, #ssssSn, #sI, #sPbH3, #ssPbH2, #sssPbH, #ssssPb,
 * #sBH2, #aOm, #sOm, #ddsP, #ssssssS, #Sm, #ddsAs, #ssssssSe, #HBd, #wHBd,
 * #HBa, #wHBa, #HBint2, #HBint3, #HBint4, #HBint5, #HBint6, #HBint7, #HBint8,
 * #HBint9, #HBint10, #HCHnX, #HCsats, #HCsatu, #HAvin, #Hother, #Hmisc,
 * #HsOH, #HdNH, #HsSH, #HsNH2, #HssNH, #HaaNH, #HsNpH3, #HssNpH2, #HsssNpH,
 * #HtCH, #HdCH2, #HdsCH, #HaaCH
 * <BR><BR>
 * Where # is n = count, S = sum, min = minimum, max = maximum.
 *
 * @author Nicola Chirico
 */
public final class QsarMEElectrTopolStateIndex
        extends DescriptorElectrTopolStateIndex
{
    public QsarMEElectrTopolStateIndex()
    {
    }

    @Override
    protected double get_min()
    {
        /*
           Implemented as PaDEL-Descriptor.

           From: PaDEL-Descriptor version 2.21
           Author: Chun Wei Yap
           Class: EStateAtomTypeDescriptor
           Method: calculate
           Availability: http://yapcwsoft.com/dd/padeldescriptor
         */
        return Double.MAX_VALUE;
    }

    @Override
    protected double get_max()
    {
        /*
           Implemented as PaDEL-Descriptor (0.0 in here preferred for clearer
           string output if the value matches minimum).

           From: PaDEL-Descriptor version 2.21
           Author: Chun Wei Yap
           Class: EStateAtomTypeDescriptor
           Method: calculate
           Availability: http://yapcwsoft.com/dd/padeldescriptor
         */
        return /*Double.MIN_VALUE*/0.0;
    }

    @Override
    protected double get_min_estate(double gmin, double estate,
            boolean is_first_value)
    {
        /*
           Implemented as PaDEL-Descriptor.

           From: PaDEL-Descriptor version 2.21
           Author: Chun Wei Yap
           Class: EStateAtomTypeDescriptor
           Method: calculate
           Availability: http://yapcwsoft.com/dd/padeldescriptor
         */
        return estate < gmin ? estate : gmin;
    }

    @Override
    protected double get_max_estate(double gmax, double estate,
            boolean is_first_value)
    {
        /*
           Implemented as PaDEL-Descriptor.

           From: PaDEL-Descriptor version 2.21
           Author: Chun Wei Yap
           Class: EStateAtomTypeDescriptor
           Method: calculate
           Availability: http://yapcwsoft.com/dd/padeldescriptor
         */
        return estate > gmax ? estate : gmax;
    }

    @Override
    protected Map<String, String> create_descr_min_map()
    {
        var all_misc_name_list = get_all_misc_name_list();

        var chem_estate_values_map = get_chem_estate_values_map();
        var min_out_map = get_min_out_map();

        for (var item : chem_estate_values_map.entrySet()) {
            String name = get_original_kier_name(item.getKey());

            List<String> value_list = item.getValue();

            if ((!all_misc_name_list.contains(name))
                    && (!value_list.isEmpty())) {
                /*
                   Implemented as PaDEL-Descriptor.

                   From: PaDEL-Descriptor version 2.21
                   Author: Chun Wei Yap
                   Class: EStateAtomTypeDescriptor
                   Method: calculate
                   Availability: http://yapcwsoft.com/dd/padeldescriptor
                 */
                Double value = Double.MAX_VALUE;

                for (String est_val : value_list) {
                    Double estate =  Double.valueOf(est_val);

                    /*
                       Implemented as PaDEL-Descriptor.

                       From: PaDEL-Descriptor version 2.21
                       Author: Chun Wei Yap
                       Class: EStateAtomTypeDescriptor
                       Method: calculate
                       Availability: http://yapcwsoft.com/dd/padeldescriptor
                    */
                    if (estate < value) {
                        value = estate;
                    }
                }

                min_out_map.put("min" + name, String.valueOf(value));
            }
        }

        return min_out_map;
    }

    @Override
    protected Map<String, String> create_descr_max_map()
    {
        var all_misc_name_list = get_all_misc_name_list();

        var chem_estate_values_map = get_chem_estate_values_map();
        var max_out_map = get_max_out_map();

        for (var item : chem_estate_values_map.entrySet()) {
            String name = get_original_kier_name(item.getKey());

            List<String> value_list = item.getValue();

            if ((!all_misc_name_list.contains(name))
                    && (!value_list.isEmpty())) {
                /*
                   Implemented as PaDEL-Descriptor (0.0 in here preferred for
                   clearer string output if the value matches minimum).

                   From: PaDEL-Descriptor version 2.21
                   Author: Chun Wei Yap
                   Class: EStateAtomTypeDescriptor
                   Method: calculate
                   Availability: http://yapcwsoft.com/dd/padeldescriptor
                 */
                Double value = /*Double.MIN_VALUE*/0.0;

                for (String est_val : value_list) {
                    Double estate =  Double.valueOf(est_val);

                    /*
                       Implemented as PaDEL-Descriptor.

                       From: PaDEL-Descriptor version 2.21
                       Author: Chun Wei Yap
                       Class: EStateAtomTypeDescriptor
                       Method: calculate
                       Availability: http://yapcwsoft.com/dd/padeldescriptor
                    */
                    if (estate > value) {
                        value = estate;
                    }
                }

                max_out_map.put("max" + name, String.valueOf(value));
            }
        }

        return max_out_map;
    }

    @Override
    protected Molecule.IntrState get_intrinsic_state(Molecule mol, IAtom atom)
    {
        return mol.calc_intrinsic_state_molconn(atom);
    }
}
