#
#coding:utf-8
#
#Author  : QCSun
#Email   : qcsun@sunhpc.com
#Times   : 2023-04-14 05:21:02
#WebSite : https://www.sunhpc.com

import os
import re
import sys
import sunhpc
import shutil
import readline

class command(sunhpc.commands.soft.command):
    pass

class Command(command):
    """
    Compilation and installation of the parallel computing software.

    <arg type="string" name="version">
    Specifies the software version. e.g,, version=x.x.x
    </arg>

    <param type="path" name="source">
    Specifies the software source path. Default: /mnt/usb
    </param>

    <param type="path" name="prefix">
    Specifies the software install path. Default: /share/apps/soft
    </param>

    <param type="path" name="cuda">
    Specifies the cuda path. Default: /usr/local/cuda
    </param>

    <param type="path" name="envs">
    Specifies the environment variable storage path. Default: /share/apps/envs
    </param>

    <example cmd='soft mpi prefix=/share/apps/soft/xxx version=x.x.x'>
    Build the command line and associated parameters for this software.
    </example>
    """
    def run(self, params, args):

        (prefix, cudapath, envs, source, version) = self.fillParams([
            ('prefix', '/share/apps/soft'),
            ('cudapath', '/usr/local/cuda'),
            ('envs', '/share/apps/envs'),
            ('source', '/mnt/usb'),
            ('version', None),
            ])

        softname = 'gromacs'
        suffname = 'tar.gz'
        dirsname = os.path.join(source, 'hpcsoft', 'Gromacs')
        verslist = self.getVersions(key=softname, suffix=suffname, dirs=dirsname)

        if len(args):
            version = args[0]

        if not version:
            self.msg('must supply an "Version Number", e.g,, version=%s' % '/'.join(verslist), 'a')

        self.create_dirs(prefix, source, envs, version, softname, suffname, dirsname)

        # Execute compilation
        self.build(cudapath, envs)

        # configure envs
        self.writeEnvs()

        # Cleanup compile cache files
        self.clean()

    def build(self, cudapath, envs):
        """Start build the software."""
        self.cwd = os.getcwd()

        names = os.listdir(self.tmpdirs)
        if self.basename not in names:
            self.msg('Unpack the file from the %s to the %s directory.' % (self.filename, self.tmpdirs))
            os.system('tar -xf %s -C %s' % (self.source, self.tmpdirs))

        build_dirs = os.path.join(self.tmpdirs, self.basename)
        os.chdir(build_dirs)

        self.msg('Starting compiling gromacs software ...')
        ask_yn = ''
        while not ask_yn:
            txt  = 'The MPI must be loaded before installing the Groamcs mpi version?\n'
            txt += '\te.g,, source %s/mpich-xxx, openmpi-xxx' % envs
            ask_yn = input('%s: ' % self.message(txt, tag='[+]', end='[no/yes/skip]'))
            if ask_yn in ['n', 'no']:
                sys.exit(0)

        self.preceding()

        cmd  = 'cmake .. -DCMAKE_INSTALL_PREFIX=%s ' % self.prefix
        cmd += '-DGMX_BUILD_OWN_FFTW=ON '
        if ask_yn in ['y', 'yes']:
            cmd += '-DGMX_MPI=ON '

        if os.path.exists(cudapath):
            cmd += '-DGMX_GPU=CUDA '
            cmd += '-DCUDA_TOOLKIT_ROOT_DIR=%s ' % cudapath

        # 安装双精度版，加上-DGMX_DOUBLE=ON，不过此时不兼容GPU加速

        cmd += '-DREGRESSIONTEST_PATH=%s' % self.regress
        os.system(cmd)
        os.system('make && make check && make install')

    def preceding(self):

        # /share/apps/soft/tmpdirs/gromacs/gromacs-2022.6/build
        if os.path.exists(self.builder): 
            shutil.rmtree(self.builder)

        # mkdir build/src/external/build-fftw/fftwBuild-prefix/src
        os.makedirs(self.fftwdir)

        # Copy FFTW to src dirs
        shutil.copyfile(self.fftwsrc, self.fftwdst)

        # Decompress regressiontests
        os.system('tar -xf %s -C %s' % (self.regrsrc, self.builder))

        os.chdir(self.builder)

    def create_dirs(self, prefix, source, envs, version, softname, suffname, dirsname):
        """Create base build directory."""

        self.basename = '%s-%s' % (softname, version)
        self.filename = '%s.%s' % (self.basename, suffname)

        self.prefix = os.path.join(prefix, softname, version)
        if not os.path.exists(self.prefix):
            os.makedirs(self.prefix)

        self.source = os.path.join(dirsname, self.filename)
        if not os.path.exists(self.source):
            self.msg('The %s does not exist,please check it.' % self.source, 'a')

        if not os.path.exists(envs):
            os.makedirs(envs)
        self.envfile = os.path.join(envs, '%s-%s' % (softname, version))

        self.tmpdirs = os.path.join(prefix, 'tmpdirs', softname)
        if not os.path.exists(self.tmpdirs):
            os.makedirs(self.tmpdirs)

        self.builder = os.path.join(self.tmpdirs, self.basename, 'build')

        self.fftwdir = os.path.join(self.builder, 'src/external/build-fftw/fftwBuild-prefix/src')
        self.fftwsrc = os.path.join(source, 'hpcsoft', 'fftw', 'fftw-3.3.8.tar.gz')
        self.fftwdst = os.path.join(self.fftwdir, 'fftw-3.3.8.tar.gz')

        self.regrsrc = os.path.join(source, 'hpcsoft', 'Gromacs', 'regressiontests-%s.%s' % (version, suffname))
        self.regress = os.path.join(self.builder, 'regressiontests-%s' % (version))

    def writeEnvs(self):
        with open(self.envfile, 'w') as f:
            f.write('#!/bin/sh\n')
            f.write('#\n# %s env config\n#\n\n' % self.basename)
            f.write('source %s/bin/GMXRC\n' % (self.prefix))

        # create shared user and group.
        self.msg('')
        self.msg('--------------------------------------------------------')
        self.msg('Create a shared group to run the %s software.' % self.basename)
        self.msg('  1, groupadd -g 888    public ')
        self.msg('  2, usermod  -G public dell   ')
        self.msg('  3, chown    -R root:public %s' % self.prefix)
        self.msg('--------------------------------------------------------')
        self.msg('')
        self.msg('  source %s' % self.envfile)
        self.msg('--------------------------------------------------------')

    def clean(self):
        """Clean the install tmp directory."""
        if os.path.exists(self.tmpdirs):
            shutil.rmtree(self.tmpdirs)



        



























