#! /usr/bin/env python
# -*- coding: utf-8 -*-

# -----------------------------------------
# PLASMA installer
# University of Tennessee Knoxville
# June 24, 2009
# ----------------------------------------



from utils import writefile, runShellCommand, killfiles, downloader
import sys
import os
import framework

class Plasma(framework.Framework):
    """ This class takes care of the PLASMA installation. """
    def __init__(self, argv, config):
        framework.Framework.__init__(self, argv, config)

    def resume(self):
        print '\n','='*40
        print 'Plasma installer is starting now. Buckle up!'
        print '='*40

        self.down_install()

        framework.Framework.resume(self)

    def write_makeinc(self):
        """ Writes the make.inc file for Plasma installation """

        sdir = os.getcwd()
        print 'Writing make.inc...',
        sys.stdout.flush()
        writefile('make.inc',"""
#/////////////////// P /// L /// A /// S /// M /// A //////////////////
#/// PLASMA is a software package provided by Univ. of Tennessee,  ///
#/// Univ. of California Berkeley and Univ. of Colorado Denver     ///
#//////////// M /// A /// K /// E /// . /// I /// N /// C /////////////

#///////////// U /// S /// E /// R ////// P /// A /// R /// T //////////

PLASMA_DIR          = """+sdir+"""

CC            = """+self.config.cc+"""
FC            = """+self.config.fc+"""
LINKER        = $(FC) 

ARCH          = ar
ARCHFLAGS     = cr
RANLIB        = """+self.ranlib+"""

OPTS          = """+self.config.ccflags+""" """+self.mangling+"""
FOPTS         =  """+self.config.fcflags+"""
LDOPTS        = """+self.config.ldflags_c+"""

LIBBLAS       = """+self.config.blaslib+"""

#///// D /// O ////// N /// O /// T ////// T /// O /// U /// C /// H /////

    # Include directory
    INC        = -I$(PLASMA_DIR)/include

    # Location of the libraries.
    LIBDIR     = -L$(PLASMA_DIR)/lib

    # Location and name of the PLASMA library.
    LIBCBLAS      = $(PLASMA_DIR)/lib/libcblas.a
    LIBCORELAPACK = $(PLASMA_DIR)/lib/libcorelapack.a
    LIBCOREBLAS   = $(PLASMA_DIR)/lib/libcoreblas.a
    LIBPLASMA     = $(PLASMA_DIR)/lib/libplasma.a

    #  All libraries required by the tester.
    LIB        = -lplasma -lcoreblas -lcorelapack -lcblas $(LIBBLAS) -lpthread -lm

#//////////////////////////////////////////////////////////////////////////

        """)
        print 'done.'

    def down_install(self):
        """ Download and install PLASMA """

        savecwd = os.getcwd()

        # creating the build and lib dirs if don't exist
        if not os.path.isdir(os.path.join(os.getcwd(),'build')):
            os.mkdir(os.path.join(os.getcwd(),'build'))

        if not os.path.isdir(os.path.join(os.getcwd(),'lib')):
            os.mkdir(os.path.join(os.getcwd(),'lib'))

        if not os.path.isdir(os.path.join(os.getcwd(),'log')):
            os.mkdir(os.path.join(os.getcwd(),'log'))

        # chdir into the build directory
        os.chdir(os.path.join(os.getcwd(),'build'))

        versions = self.versions

        if self.src_path: # if the parth to the source code was provided
          #FIXME: need to check if the destination directory is not the same

          # the only version is the custom one
          versions = ("CUSTOM",)
          cur_fname = "plasma_" + versions[0] + ".tar.gz"

          # copy recursively to the current directory
          runShellCommand("cp -r " + self.src_path + " " + cur_fname[:-7])

          # create a dummy file
          dummy_fname = "abcdefg.txt"
          f = open("abcdefg.txt", "w")
          f.write(dummy_fname)
          f.close()

          # create a TAR archive with a dummy file
          runShellCommand("tar -cf " + cur_fname[:-3] + " " + dummy_fname)

          os.remove(dummy_fname) # delete a dummy file

          # compress the TAR archive with a dummy file
          runShellCommand("gzip " + cur_fname[:-3])
          # now we should have plasma_CUSTOM.tar.gz with a dummy file

        for ver in versions:
            cur_fname = "plasma_" + ver + ".tar.gz"

            if not os.path.isfile(os.path.join(os.getcwd(), cur_fname)):
                cur_url = self.urlbase + "/" + cur_fname
                print 'Downloading PLASMA from', cur_url
                downloader(cur_url, self.downcmd)
            else:
                print 'Already downloaded PLASMA to', cur_fname

            if os.path.isfile(os.path.join(os.getcwd(), cur_fname)):
                break

        comm = "gunzip -f " + cur_fname
        (output, error, retz) = runShellCommand(comm)
        if retz:
            print "\n\nPlasma: cannot unzip " + cur_fname
            print "stderr:\n",'*'*40,'\n',error,'\n','*'*40
            sys.exit()


        cur_tar = cur_fname[:-3]
        comm = "tar xf " + cur_tar
        (output, error, retz) = runShellCommand(comm)
        if retz:
            print "\n\nPLASMA: cannot untar " + cur_tar
            print 'stderr:\n','*'*40,'\n',error,'\n','*'*40
            sys.exit()
        os.remove(cur_tar)

#        os.chdir(os.path.join(os.getcwd(),'plasma'))
        comm = 'ls -1 | grep plasma_ | grep -v tar'
        (output, error, retz) = runShellCommand(comm)
        if retz:
            print '\n\PLASMA: error changing to PLASMA dir'
            print 'stderr:\n','*'*40,'\n','   ->  no plasma directory found','\n','*'*40
            sys.exit()
        rep_name = output.replace ("\n","")
        print 'Installing ',rep_name,'...'
        os.chdir(os.path.join(os.getcwd(),rep_name))

        self.write_makeinc()

        print 'Compiling PLASMA...',
        sys.stdout.flush()
        comm = self.make+' lib'
        (output, error, retz) = runShellCommand(comm)
        if retz:
            print '\n\nPLASMA: error building PLASMA'
            print 'stderr:\n','*'*40,'\n',error,'\n','*'*40
            writefile(os.path.join(savecwd,'log/plasmalog'), output+error)
            sys.exit()

        liblog = os.path.join(savecwd,'log/plasmalog')
        writefile(liblog, output+error)
        print 'Installation of PLASMA successful..'
        print '(log is in ',liblog,')'

        if self.testing:

            # Open the file for writing the output and errors
            testlog = os.path.join(savecwd,'log/plasmatestlog')
            f = open(testlog, 'w')

            # Compiling tests
            print 'Compiling tests...',
            sys.stdout.flush()
            comm = self.make+ ' test'
            (output, error, retz) = runShellCommand(comm)
            if retz:
                print '\n\nPLASMA: error building PLASMA test routines'
                print 'stderr:\n','*'*40,'\n',error,'\n','*'*40
                f.write(output+error)
                f.close()
                sys.exit()
            print 'done'
            f.write(output+error)

            # Running in
            os.chdir(os.path.join(os.getcwd(),'testing'))
            print 'Running PLASMA tests on',self.nbcores, 'cores...(takes some time, feel free to grab a coffee!)'
            print '--> testing ...',
            sys.stdout.flush()
            comm = './plasma_testing.py ' + str(self.nbcores)
            (output, error, retz) = runShellCommand(comm, sys.stdout)
            if retz:
                print '\n\nPLASMA: Testing failed... '
                print 'stderr:\n','*'*40,'\n',error,'\n','*'*40
                f.write(output+error)
                f.close()
                sys.exit()
            print 'done'
            print error
            f.write(output+error)

            # Running testing/lin
            os.chdir(os.path.join(os.getcwd(),'lin'))
            print '--> testing/lin...',
            sys.stdout.flush()
            comm = './lapack_testing.py'
            (output, error, retz) = runShellCommand(comm, sys.stdout)
            if retz:
                print '\n\nPLASMA: Testing failed... '
                print 'stderr:\n','*'*40,'\n',error,'\n','*'*40
                f.write(output+error)
                f.close()
                sys.exit()
            print 'done'
            print error
            f.write(output+error)

            f.close()
            print '(log is in ',testlog,')'

            os.chdir(os.path.join(os.getcwd(),'../..'))

        os.rename('lib/libplasma.a',os.path.join(savecwd,'lib/libplasma.a'))
        os.rename('lib/libcblas.a',os.path.join(savecwd,'lib/libcblas.a'))
        os.rename('lib/libcorelapack.a',os.path.join(savecwd,'lib/libcorelapack.a'))
        os.rename('lib/libcoreblas.a',os.path.join(savecwd,'lib/libcoreblas.a'))

        self.plasmalib = os.path.join(savecwd,'lib/libplasma.a ')
        self.cblaslib = os.path.join(savecwd,'lib/libcblas.a ')
        self.corelapacklib = os.path.join(savecwd,'lib/libcorelapack.a ')
        self.coreblaslib = os.path.join(savecwd,'lib/libcoreblas.a ')

        os.chdir(savecwd)
        print "done. PLASMA is installed. Use it in moderation :-)"
