#! /usr/bin/env python

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



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


class Plasma(Frame):
    """ This class takes care of the PLASMA installation. """
    def __init__(self):
        print '\n','='*40
        print 'Plasma installer is starting now. Buckle up!'
        print '='*40

        self.down_install()






    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.cc+"""
FC            = """+self.fc+"""
LINKER        = $(FC) 

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

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

LIBBLAS       = """+self.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'))

        print 'Downloading PLASMA from',self.plasmaurl,'\n'

        if(not os.path.isfile(os.path.join(os.getcwd(),getURLName(self.plasmaurl)))):
            downloader(self.plasmaurl, self.downcmd)

        comm = 'gunzip -f plasma.tar.gz'
        (output, error, retz) = runShellCommand(comm)
        if(retz != 0):
            print '\n\nPlasma: cannot unzip plasma.tar.gz'
            print 'stderr:\n','*'*40,'\n',error,'\n','*'*40
            sys.exit()


        comm = 'tar xf plasma.tar'
        (output, error, retz) = runShellCommand(comm)
        if(retz != 0):
            print '\n\nPLASMA: cannot untar plasma.tar'
            print 'stderr:\n','*'*40,'\n',error,'\n','*'*40
            sys.exit()
        os.remove('plasma.tar')

#        os.chdir(os.path.join(os.getcwd(),'plasma'))
        comm = 'ls -1 | grep plasma_ '
        (output, error, retz) = runShellCommand(comm)
        if(retz != 0):
            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 != 0):
            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 == 1):

            # 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 != 0):
                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)
            if(retz != 0):
                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)
            if(retz != 0):
                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 ')
        Frame.plasmalib = os.path.join(savecwd,'lib/libplasma.a ')
        self.cblaslib  = os.path.join(savecwd,'lib/libcblas.a ')
        Frame.cblaslib = os.path.join(savecwd,'lib/libcblas.a ')
        self.corelapacklib  = os.path.join(savecwd,'lib/libcorelapack.a ')
        Frame.corelapacklib = os.path.join(savecwd,'lib/libcorelapack.a ')
        self.coreblaslib  = os.path.join(savecwd,'lib/libcoreblas.a ')
        Frame.coreblaslib = os.path.join(savecwd,'lib/libcoreblas.a ')

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