# -*- coding: utf-8 -*-

"""Functions for handling CIF files"""

import logging

logger = logging.getLogger(__name__)

bond_order = {1: 'SING', 2: 'DOUB', 3: 'TRIP'}


class CIFMixin:
    """A mixin for handling CIF files."""

    def to_cif_text(self, configuration=None):
        """Create the text of a CIF file from the confguration.

        Parameters
        ----------
        configuration : int = None
            The configuration to use, defaults to the current configuration.

        Returns
        -------
        text : str
            The text of the file.
        """

        lines = []

        atoms = self.atoms

        if configuration is None:
            configuration = self.current_configuration

        # Get the chemical formula
        formula, empirical_formula, Z = self.formula(configuration)
        formula = ' '.join(formula)
        empirical_formula = ''.join(empirical_formula)

        # And created the file, line-by-line
        lines = []
        lines.append('# Generated by MolSSI SEAMM')
        lines.append(f"data_{empirical_formula}")

        # Cell information
        if self.periodicity == 3:
            cell = self['cell'].cell(configuration)
            a, b, c, alpha, beta, gamma = cell.parameters
            volume = cell.volume
            lines.append("_symmetry_space_group_name_H-M   'P 1'")
            lines.append(f'_cell_length_a   {a}')
            lines.append(f'_cell_length_b   {b}')
            lines.append(f'_cell_length_c   {c}')
            lines.append(f'_cell_angle_alpha   {alpha}')
            lines.append(f'_cell_angle_beta    {beta}')
            lines.append(f'_cell_angle_gamma   {gamma}')
            lines.append('_symmetry_Int_Tables_number   1')
            lines.append(f'_cell_volume   {volume}')
            lines.append(f'_cell_formula_units_Z   {Z}')
            lines.append('loop_')
            lines.append(' _symmetry_equiv_pos_site_id')
            lines.append(' _symmetry_equiv_pos_as_xyz')
            lines.append("  1  'x, y, z'")

        lines.append(f'_chemical_formula_structural   {empirical_formula}')
        lines.append(f"_chemical_formula_sum   '{formula}'")

        # The atoms
        lines.append('loop_')
        lines.append(' _atom_site_type_symbol')
        lines.append(' _atom_site_label')
        lines.append(' _atom_site_symmetry_multiplicity')
        lines.append(' _atom_site_fract_x')
        lines.append(' _atom_site_fract_y')
        lines.append(' _atom_site_fract_z')
        lines.append(' _atom_site_occupancy')

        # Need unique names
        if 'names' in atoms:
            original_names = atoms.get_column('names', configuration)
        else:
            original_names = atoms.symbols(configuration)

        names = []
        tmp = {}
        for name in original_names:
            if name in tmp:
                tmp[name] += 1
                names.append(name + str(tmp[name]))
            else:
                tmp[name] = 1
                names.append(name)

        UVW = atoms.coordinates(
            configuration=configuration, fractionals=True, in_cell='molecule'
        )

        symbols = atoms.symbols(configuration)
        for element, name, uvw in zip(symbols, names, UVW):
            u, v, w = uvw
            lines.append(f'{element} {name}  1  {u:.3f} {v:.3f} {w:.3f}  1')

        # And that is it!
        return '\n'.join(lines)

    def to_mmcif_text(self, configuration=None):
        """Create the text of a mmCIF file from the confguration.

        Parameters
        ----------
        configuration : int = None
            The configuration to use, defaults to the current configuration.

        Returns
        -------
        text : str
            The text of the file.
        """

        lines = []

        atoms = self.atoms
        bonds = self.bonds

        if configuration is None:
            configuration = self.current_configuration

        # Get the chemical formula
        formula, empirical_formula, Z = self.formula(configuration)
        formula = ' '.join(formula)
        empirical_formula = ''.join(empirical_formula)

        # And created the file, line-by-line
        lines = []
        lines.append('# Generated by MolSSI SEAMM')
        lines.append(f"data_{empirical_formula}")
        lines.append(f"_chem_comp.name '{formula}'")
        lines.append(f"_chem_comp.id '{empirical_formula}'")
        lines.append(f"_chem_comp.formula   '{formula}'")

        # Cell information
        if self.periodicity == 3:
            cell = self['cell'].cell(configuration)
            a, b, c, alpha, beta, gamma = cell.parameters
            volume = cell.volume
            lines.append("_symmetry_space_group_name_H-M   'P 1'")
            lines.append(f'_cell_length_a   {a}')
            lines.append(f'_cell_length_b   {b}')
            lines.append(f'_cell_length_c   {c}')
            lines.append(f'_cell_angle_alpha   {alpha}')
            lines.append(f'_cell_angle_beta    {beta}')
            lines.append(f'_cell_angle_gamma   {gamma}')
            lines.append('_symmetry_Int_Tables_number   1')
            lines.append(f'_cell_volume   {volume}')
            lines.append(f'_cell_formula_units_Z   {Z}')
            lines.append('loop_')
            lines.append(' _symmetry_equiv_pos_site_id')
            lines.append(' _symmetry_equiv_pos_as_xyz')
            lines.append("  1  'x, y, z'")

        lines.append(f'_chemical_formula_structural   {empirical_formula}')
        lines.append(f"_chemical_formula_sum   '{formula}'")

        # The atoms
        lines.append('loop_')
        lines.append(' _atom_site_type_symbol')
        lines.append(' _atom_site_label')
        lines.append(' _atom_site_symmetry_multiplicity')
        lines.append(' _atom_site_fract_x')
        lines.append(' _atom_site_fract_y')
        lines.append(' _atom_site_fract_z')
        lines.append(' _atom_site_occupancy')

        # Need unique names
        if 'names' in atoms:
            original_names = atoms.get_column('names', configuration)
        else:
            original_names = atoms.symbols(configuration)

        names = []
        tmp = {}
        for name in original_names:
            if name in tmp:
                tmp[name] += 1
                names.append(name + str(tmp[name]))
            else:
                tmp[name] = 1
                names.append(name)

        XYZ = atoms.coordinates(
            configuration=configuration, in_cell='molecule'
        )
        XYZa = atoms.coordinates(configuration=configuration)

        symbols = atoms.symbols(configuration)
        for element, name, xyza, xyz in zip(symbols, names, XYZa, XYZ):
            xa, ya, za = xyza
            x, y, z = xyz
            lines.append(
                f'MOL1 {name} {element} {xa:.3f} {ya:.3f} {za:.3f} '
                f'{x:.3f} {y:.3f} {z:.3f} HET 1'
            )

        # The bonds
        lines.append('#')
        lines.append('loop_')
        lines.append(' _chem_comp_bond.comp_id')
        lines.append(' _chem_comp_bond.atom_id_1')
        lines.append(' _chem_comp_bond.atom_id_2')
        lines.append(' _chem_comp_bond.value_order')
        for row in bonds.bonds(configuration=configuration):
            i = row['i']
            j = row['j']
            order = bond_order[row['bondorder']]
            nm1 = names[i - 1]
            nm2 = names[j - 1]
            lines.append(f'MOL1 {nm1} {nm2} {order}')

        # And that is it!
        return '\n'.join(lines)
