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

import sys
import os
import os.path as osp
import re
import shutil
import time
import unittest

from common import dict_conf, execcmd, tmpdir
from data   import study_export, meshtool_export

import asrun
from asrun.core         import magic
from asrun.installation import aster_root
from asrun.run          import AsRunFactory, RunAsterError
from asrun.profil       import AsterProfil
from asrun.config       import AsterConfig
from asrun.calcul       import AsterCalcul, AsterCalcParametric, parse_submission_result
from asrun.job          import parse_actu_result
from asrun.execution    import build_test_export
from asrun.system       import local_host


class TestRunStudy(unittest.TestCase):

    def setUp(self):
        self.export = osp.join(tmpdir, "study.export")
        with open(self.export, "w") as f:
            f.write(study_export % dict_conf)
        self.base_results = '%(TMPDIR)s/study.2.base_results' % dict_conf
        self.named_result = '%(TMPDIR)s/info_cpu' % dict_conf
        self.open_terminal = os.environ.get('DISPLAY') is not None and False


    def test01_from_cmdline(self):
        cmd = dict_conf["as_run"] + [self.export]
        iret = execcmd(cmd, "study.1")
        assert iret == 0


    def test02_using_api(self):
        run = AsRunFactory()

        prof = AsterProfil(run=run, filename=self.export)
        if self.open_terminal:
            prof['follow_output'] = 'yes'

        # etude simple
        nomjob = 'study.2'
        prof1 = prof.copy()
        prof1['nomjob'] = nomjob
        prof1.Set('R', { 'type' : 'base', 'isrep' : True, 'ul' : 0 , 'compr' : False,
                       'path' : self.base_results })
        # test named result
        prof1.Set('R', { 'type' : 'nom', 'isrep' : False, 'ul' : 0 , 'compr' : False,
                       'path' : self.named_result })
        # add a file with CR
        prof1.Set('D', { 'type' : 'libr', 'isrep' : False, 'ul' : 38 , 'compr' : False,
                       'path' : osp.join(dict_conf["DATA"], "with_win_CR.export") })
        pid = run.get_pid()
        calc1 = AsterCalcul(run, prof=prof1, pid=pid)
        jret, out = calc1.start()
        calc1.wait()
        assert run.GetGrav(calc1.diag) <= 1, calc1.diag
        assert osp.isfile(calc1.flash('output'))
        assert osp.isfile(self.named_result)

        # etude template
        nomjob = 'study.3'
        prof2 = prof.copy()
        prof2['nomjob'] = nomjob
        prof2.Set('R', {'type' : 'repe', 'isrep' : True, 'ul' : 0 ,
                      'path' : 'PWD', 'compr' : False})
        pid = os.getpid()
        calc2 = AsterCalcParametric(run, label="P1", prof=prof2, pid=pid,
                               values={ 'P1' : 12. }, keywords={},
                               resudir="%(TMPDIR)s/study.3.resu" % dict_conf)
        jret, out = calc2.start()
        calc2.wait()
        assert run.GetGrav(calc2.diag) <= 1, calc2.diag
        assert osp.isfile(calc2.flash('output'))
        with open(calc2.flash('output'), 'r') as f:
            content = f.read()
        assert re.search('PARAMETER *= *12', content) is not None
        calc1.kill()
        assert not osp.isfile(calc1.flash('output'))
        calc2.kill()
        assert not osp.isfile(calc2.flash('output'))

    @unittest.skip("should be run in a SALOME session")
    def test03_stanley_using_api(self):
        nomjob = 'study.4'
        pid = os.getpid()
        run = AsRunFactory(num_job=pid)
        prof = AsterProfil(run=run, filename=self.export)
        prof['nomjob'] = nomjob
        #prof.Set('R', {'type' : 'base', 'isrep' : True, 'ul' : 0 ,
        #               'path' : 'PWD/base_results', 'compr' : False})
        prof['special'] = 'stanley%%NEXT%%R base %s D 0' % self.base_results

        calcul = AsterCalcul(run, prof=prof)
        jret, out = calcul.start()
        calcul.wait()
        with open(calcul.flash('output'), 'r') as f:
            output = f.read()
        assert os.environ.get('DISPLAY') is not None
        assert run.GetGrav(calcul.diag) == 1, calcul.diag
        assert output.find('STANLEY_37') > -1
        calcul.kill()


    def test04_meshtool_cmdline(self):
        export = osp.join(tmpdir, "meshtool.export")
        with open(export, "w") as f:
            f.write(meshtool_export % dict_conf)
        cmd = dict_conf["as_run"] + ["--serv", export]
        iret, out = execcmd(cmd, "study.4", return_output=True)
        nomjob = "meshtool_cmdline_mesh"
        assert iret == 0
        jobid, queue, studyid = parse_submission_result(out)
        assert jobid.strip() != ""
        assert studyid.strip() != "" and studyid == jobid
        etat = 'RUN'
        i = 0
        while etat != 'ENDED':
            i += 1
            cmd = dict_conf["as_run"] + ["--actu", jobid, nomjob, "interactif"]
            iret, out = execcmd(cmd, "study.5", return_output=True)
            etat, diag, node, tcpu, wrk, queue = parse_actu_result(out)
            if etat != "ENDED":
                time.sleep(0.5)
            assert i < 20, "etat='%s', output='%s'" % (etat, out)
        run = AsRunFactory()
        assert run.GetGrav(diag) <= 1, diag
        with open(osp.join(tmpdir, 'mesh_out'), "r") as f:
            mesh_out = f.read()
        assert re.search("FINSF", mesh_out)
        cmd = dict_conf["as_run"] + ["--del", jobid, nomjob, "interactif"]
        iret, out = execcmd(cmd, "study.6", return_output=True)
        assert iret == 0


    def test05_error(self):
        run = AsRunFactory()
        magic.set_stdout(osp.join(tmpdir, "study.7.out"))
        prof = AsterProfil(run=run, filename=self.export)

        # etude simple
        nomjob = 'study.7'
        prof['nomjob'] = nomjob
        prof['mode'] = "invalid_mode_for_test"  # automatically redefine to interactif
        run.config['interactif'] = 'non'
        pid = run.get_pid()
        calc = AsterCalcul(run, prof=prof, pid=pid)
        jret, out = calc.start()
        assert jret == 4, (jret, out)


    def test06_usr1(self):
        run = AsRunFactory()
        vers = dict_conf['ASTER_VERSION']
        assert vers is not None, "default_vers is None! Check aster configuration file"
        REPREF = run.get_version_path(vers)
        run.PrintExitCode = False
        ficconf = osp.join(REPREF, 'config.txt')
        conf = AsterConfig(ficconf, run)
        prof = build_test_export(run, conf, REPREF, [], "ssnp125a")
        assert len(prof.Get("D", "comm")) >= 1, "perhaps this testcase no longer exists ?"
        prof["version"] = vers
        prof["actions"] = "make_etude"
        prof["noeud"] = local_host
        if self.open_terminal:
            prof['follow_output'] = 'yes'

        # for debugging
        #prof.Set('D', {'type' : 'exec', 'isrep' : False, 'ul' : 0 ,
                       #'path' : '/home/courtois/dev/issue15190/aster.exe', 'compr' : False})
        # to check base copy
        base_results = osp.join(tmpdir, 'test06_usr1.base_results')
        prof.Set('R', {'type' : 'base', 'isrep' : True, 'ul' : 0,
                       'path' : base_results, 'compr' : False})
        # etude simple
        nomjob = 'study.8'
        prof['nomjob'] = nomjob
        pid = run.get_pid()
        calc = AsterCalcul(run, prof=prof, pid=pid)
        jret, out = calc.start()
        time.sleep(5)
        cmd = dict_conf["as_run"] + ["--del", "--signal=USR1", pid, nomjob, "interactif"]
        iret, out = execcmd(cmd, nomjob, return_output=True)
        calc.wait()
        # this test may fail while issue15190 has not been fixed
        assert run.GetGrav(calc.diag) == run.GetGrav("<S>"), calc.diag
        assert osp.isdir(base_results)
        assert osp.isfile(calc.flash('output'))
        shutil.copy(calc.flash('output'), tmpdir)
        calc.kill()


if __name__ == "__main__":
    unittest.main()
