import config.package
import os

class Configure(config.package.CMakePackage):
  def __init__(self, framework):
    config.package.CMakePackage.__init__(self, framework)
    self.versionname       = 'AMREX_GIT_VERSION'
    self.gitcommit         = '22.10'
    self.download          = ['git://https://github.com/AMReX-Codes/amrex.git','https://github.com/AMReX-Codes/amrex/archive/'+self.gitcommit+'.tar.gz']
    self.includes          = ['AMReX.H']
    self.liblist           = [['libamrex.a']]
    self.versioninclude    = 'AMReX_Config.H'
    self.functions         = ['amrex_fi_init']
    self.hastests          = 1
    self.hastestsdatafiles = 1
    self.precisions        = ['double']
    self.buildLanguages    = ['Cxx']
    self.minCxxVersion     = 'c++14'
    self.useddirectly      = 0
    self.builtafterpetsc   = 1
    self.minCmakeVersion   = (3,14,0)
    return

  def setupHelp(self, help):
    import nargs
    config.package.CMakePackage.setupHelp(self, help)

  def setupDependencies(self, framework):
    config.package.CMakePackage.setupDependencies(self, framework)
    self.blasLapack     = framework.require('config.packages.BlasLapack',self)
    self.mpi            = framework.require('config.packages.MPI',self)
    #  requires HYPRE install because AMReX CMake requires HYPRE in path to compile AMReX PETSc code
    #  Src/Extern/PETSc/AMReX_PETSc.cpp:10:10: fatal error: 'AMReX_HypreABec_F.H' file not found
    self.hypre          = framework.require('config.packages.hypre',self)
    self.cuda           = framework.require('config.packages.CUDA',self)
    self.hip            = framework.require('config.packages.HIP',self)
    self.sycl           = framework.require('config.packages.SYCL',self)
    self.openmp         = framework.require('config.packages.OpenMP',self)
    self.odeps          = [self.mpi,self.blasLapack,self.cuda,self.hip,self.sycl,self.openmp]
    self.deps           = [self.hypre,self.mpi,self.blasLapack]
    return

  def formCMakeConfigureArgs(self):
    args = config.package.CMakePackage.formCMakeConfigureArgs(self)
    args.append('-DAMReX_EB=YES')
    args.append('-DAMReX_LINEAR_SOLVERS=YES')
    args.append('-DAMReX_PARTICLES=YES')
    args.append('-DAMReX_PETSC=YES')
    args.append('-DAMReX_HYPRE=YES')
    if hasattr(self.compilers, 'FC'):
      args.append('-DAMReX_FORTRAN_INTERFACES=YES')

    GPUBackend = ''
    if self.cuda.found:
      GPUBackend = 'CUDA'
      # Prefer cmake options instead of -DAMReX_CUDA_ARCH
      args.extend(self.cuda.getCmakeCUDAArchFlag())
    elif self.hip.found:
      GPUBackend = 'HIP'
      args.append('-DCMAKE_HIP_ARCHITECTURES="'+self.hip.hipArch+'"')
    elif self.sycl.found:
      GPUBackend = 'SYCL'

    if GPUBackend:
      args.append('-DAMReX_GPU_BACKEND='+GPUBackend)

    if self.argDB['prefix'] and not 'package-prefix-hash' in self.argDB:
      args.append('-DPETSC_DIR='+os.path.abspath(os.path.expanduser(self.argDB['prefix'])))
      args.append('-DPETSC_ARCH=""')
      args.append('-DHYPRE_ROOT='+os.path.abspath(os.path.expanduser(self.argDB['prefix'])))
    else:
      args.append('-DPETSC_DIR='+os.path.join(self.petscdir.dir))
      args.append('-DPETSC_ARCH='+self.arch)
      args.append('-DHYPRE_ROOT='+os.path.join(self.petscdir.dir,self.arch))
    if self.argDB['prefix']:
      args.append('-DHYPRE_ROOT='+os.path.abspath(os.path.expanduser(self.argDB['prefix'])))
    else:
      args.append('-DHYPRE_ROOT='+os.path.join(self.petscdir.dir,self.arch))
    return args

  def Install(self):
    import os

    output,err,ret  = config.package.Package.executeShellCommand('git describe --abbrev=12 --dirty --always --tags', cwd=self.packageDir)
    if not err and not ret:
      self.foundversion = output

    args = self.formCMakeConfigureArgs()
    if self.download and self.argDB['download-'+self.downloadname.lower()+'-cmake-arguments']:
       args.append(self.argDB['download-'+self.downloadname.lower()+'-cmake-arguments'])
    args = ' '.join(args)
    conffile = os.path.join(self.packageDir,self.package+'.petscconf')
    fd = open(conffile, 'w')
    fd.write(args)
    fd.close()

    if not self.installNeeded(conffile):
      return self.installDir
    if not self.cmake.found:
      raise RuntimeError('CMake not found, needed to build '+self.PACKAGE+'. Rerun configure with --download-cmake.')

    # effectively, this is 'make clean'
    folder = os.path.join(self.packageDir, 'petsc-build')
    if os.path.isdir(folder):
      import shutil
      shutil.rmtree(folder)
    os.mkdir(folder)

    # these checks are usually done in configureLibrary
    if self.argDB['prefix'] and not 'package-prefix-hash' in self.argDB:
      self.directory = os.path.abspath(os.path.expanduser(self.argDB['prefix']))
      self.include_a = '-I'+os.path.join(os.path.abspath(os.path.expanduser(self.argDB['prefix'])),'include')
      self.lib_a = [os.path.join(os.path.abspath(os.path.expanduser(self.argDB['prefix'])),'lib',self.liblist[0][0])]
    else:
      self.directory = self.petscdir.dir
      self.include_a = '-I'+os.path.join(self.petscdir.dir,self.arch,'include')
      self.lib_a = [os.path.join(self.petscdir.dir,self.arch,'lib',self.liblist[0][0])]
    self.found_a     = 1
    self.addMakeMacro('AMREX_LIB',' '.join(map(self.libraries.getLibArgument, self.lib_a)))
    self.addMakeMacro('AMREX_INCLUDE',self.include_a)

    # if installing prefix location then need to set new value for PETSC_DIR/PETSC_ARCH
    if self.argDB['prefix'] and not 'package-prefix-hash' in self.argDB:
       carg = 'PETSC_DIR='+os.path.abspath(os.path.expanduser(self.argDB['prefix']))+' PETSC_ARCH="" '
       prefix = os.path.abspath(os.path.expanduser(self.argDB['prefix']))
    else:
       prefix = os.path.join(self.petscdir.dir,self.arch)
       carg = ''

    self.addPost(os.path.join(self.packageDir,'petsc-build'), [carg + ' ' + self.cmake.cmake + ' .. ' + args, self.make.make_jnp + '  ' + self.makerulename,
                                                              '${OMAKE} install'])
    return self.installDir
