#  Copyright (C) 2019 The authors of Py-ChemShell
#  This file was written by Rowan Hanson and Andrew Logsdail.
#  We are particularly grateful to support from CCP5 for this work.
#
#  This file is part of Py-ChemShell.
#
#  Py-ChemShell 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 of the
#  License, or (at your option) any later version.
#
#  Py-ChemShell 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 Py-ChemShell.  If not, see
#  <http://www.gnu.org/licenses/>.

from numpy import asarray
from ...data import atomicdata, unitconvert

def parse(filename, _regex=None, receiver=None, prefix='', **kwargs):
    '''
    Parse a CONFIG file and return a Fragment object
        Parameters:
            filename (str)
                The input filename (presumably CONFIG) the needs to be read.
            _regex (str):
                ??? Can this be removed ???
            receiver (chemsh.Fragment)
                The Fragment object in to which all the information is to be stored
    '''

    from numpy   import char
    from os      import path
    from ...base import forcefield

    # YL 13/08/2022: path prefix
    filename = path.join(prefix, filename)

    # Load content into variable (reduce IO with reading all data once)
    with open(filename, 'r') as fp:
        content = fp.read().splitlines()

    # RH: The following is taken from the second line of the CONFIG file in format 'coords_velocity_forces', 'periodicity', 'natoms'.
    # coords_velocity_forces == coordinates, velocities and forces -- one, two or all of these will be present in the file.
    # pbc == periodic boundary conditions -- choice from type 0, 1, 2, 3, or 6.
    # natoms == total number of atoms present in the file.
    # AL, Oct 2019: Replaced genfromtxt with list manipulation as it reduces io
    # YL 10/12/2019: natoms may not appear
    coords_velocity_forces, pbc = asarray(content[1].split(), dtype=int)[:2]

    # YL 10/12/2019: vectors may not appear
    try:
        receiver.cell.vectors = asarray([line.split()[0:3] for line in content[2:5]], dtype=float)*unitconvert.Angstrom2Bohr
        start_line = 5
    except:
        start_line = 2

    names = asarray([line.split()[0] for line in content[start_line::2+coords_velocity_forces]], dtype=str)

    # Collecting the atomic coordinates
    # TODO: core/shell
    coords = asarray([line.split()[0:3] for line in content[start_line+1::2+coords_velocity_forces]], dtype=float)

    # The following two IF statements are used to collect the atomic velocity and forces if they are presented in the file. 
    if coords_velocity_forces >= 1:
        velocity = asarray([line.split()[0:3] for line in content[start_line+2::2+coords_velocity_forces]], dtype=float)
        if coords_velocity_forces == 2:
            forces = asarray([line.split()[0:3] for line in content[start_line+3::2+coords_velocity_forces]], dtype=float)

    # Declare list objects to store bulk of the information taken from CONFIG file
    elements    = []
    #environment = [] # RH: see comments below first mention of 'atominf'.

    for atominf in names:
        atom = atominf.split()[0]

        # RH: CONFIG files can either state the atom only, e.g. 'C', 'Ca', 'X' etc., or they can state the environment of that atom as well, e.g. 'CA', 'CaA' etc..
        #     This therefore requires something like the statements below to maintain only the atomic symbols.
        #     environment has also been collected in the below statments, however is not stored nor recalled. This may be something that is required at a later stage of working.
        # NOTE: Sometimes other dummy atoms (e.g. not 'X') are used in CONFIG files. ...data/atomicdata.py only accounts for 'X'/'x'.
        #       This may cause an issue, whereby either the CONFIG file will need to be editted by this parser or ...data/atomicdata.py will need to be amended.
        if len(atominf) > 1:
            if atominf.split()[0][-1:].islower():
                atom = atominf.split()[0]
            elif len(atominf) > 2:
                atom = atominf.split()[0][:-2]
                environment = atominf.split()[-1:]
            else:
                atom = atominf.split()[0][:-1]
                environment = atominf.split()[-1:]

        # RH: Collecting the atomic numbers in a list.
        elements.append(atom.title())

    # RH: collecting the atomic numbers, coordinates, velocity* and forces** and all other data
    receiver.natoms = names.shape[0]
    receiver.znums  = forcefield.names2znums(char.encode(elements))
    receiver.coords = [xyz * unitconvert.Angstrom2Bohr for xyz in coords]

    # AL, Oct 2019: I've moved this after znums assignment, so that the names assignment isn't overwritten
    receiver.names        = names

    # AL, Oct 2019. I have a concern about the units here - do they need multiplying by Angstrom2Bohr
    # This is currently untested/unused, so commenting it out as a safety precaution
    # if coords_velocity_forces >= 1:
    #     receiver.velocity = velocity
    #     if coords_velocity_forces == 2:
    #         receiver.forces = forces


# YL 11/12/2019: TODO move the existing code in DL_POLY interface here
def write(filename, frag, **kwargs):
    '''Writer'''

    
