""" Unit tests for the Dirac interface module
"""
# pylint: disable=no-member, protected-access, missing-docstring
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
import logging

import six
from pprint import pformat
import pytest
from mock import MagicMock, call

from DIRAC.Interfaces.API.Dirac import Dirac
from DIRAC import S_OK

logging.basicConfig()
LOG = logging.getLogger('TestDirac')
LOG.setLevel(logging.ERROR)


@pytest.fixture
def dirac():
  d = Dirac()
  d.log = MagicMock(name="Log")
  d.log.debug = d.log
  d.log.info = d.log
  d.log.notice = d.log
  d.log.verbose = d.log
  d.log.error = d.log
  d.log.warn = d.log
  return d


@pytest.fixture
def job():
  from DIRAC.Interfaces.API.Job import Job
  job = Job(stdout='printer', stderr='/dev/null')
  job.setInputSandbox(['LFN:/vo/user/i/initial/important.tar.gz',
                       '/abspath/absfile.xml',
                       'file_in_pwd.xml'])
  return job


@pytest.fixture
def osmock():
  os = MagicMock(return_value=False, name="OS")
  os.environ = dict()
  os.environ['DIRAC'] = '/root/dirac'

  def expandMock(*args, **kwargs):
    if 'DIRACROOT' in os.environ and \
       'DIRACROOT' in args[0]:
      return args[0].replace('$DIRACROOT', os.environ['DIRACROOT'])
    return args[0]

  def existsMock(*args, **kwargs):
    print("exists", args)
    if any(f in args[0] for f in ('jobDescription', '/pwd/file_in_pwd.xml')):
      return True
    if 'absfile' in args[0] and args[0].startswith('/abspath'):
      return True
    return False

  def joinMock(*args):
    path = '/'
    for l in args:
      path += l.strip('/') + '/'
    return path.rstrip('/')

  os.getcwd.side_effect = ['/pwd/'] + ['/pwd/tempFolder/'] * 100

  os.path.expandvars.side_effect = expandMock
  os.path.exists.side_effect = existsMock
  os.path.isabs.side_effect = lambda x: x.startswith('/')
  os.path.isdir.return_value = False
  os.path.join.side_effect = joinMock
  os.path.basename.side_effect = lambda x: x.rsplit('/', 1)[-1]
  return os


@pytest.fixture
def confMock():
  gConf = MagicMock(name="gConfig")

  def getVal(*args, **kwargs):
    if '/LocalSite/Root' in args[0]:
      return '/root/dirac'
    if len(args) == 2:
      return args[1]
    return 'defaultValue'
  gConf.getValue.side_effect = getVal
  return gConf


def test_basicJob(dirac):
  jdl = "Parameter=Value;Parameter2=Value2"
  ret = dirac._Dirac__getJDLParameters(jdl)
  assert ret['OK']
  assert 'Parameter' in ret['Value']
  assert ret['Value']['Parameter'] == 'Value'
  assert 'Parameter2' in ret['Value']
  assert ret['Value']['Parameter2'] == 'Value2'


def test_JobJob(dirac, job):
  ret = dirac._Dirac__getJDLParameters(job)
  assert ret['OK']
  assert ret['Value']['StdOutput'] == 'printer'
  assert ret['Value']['StdError'] == '/dev/null'


def test_runLocal(dirac, job, mocker, osmock, confMock):
  mocker.patch('DIRAC.Interfaces.API.Dirac.os', new=osmock)
  mocker.patch('DIRAC.Interfaces.API.Dirac.tarfile', new=MagicMock(return_value=False))
  if six.PY2:
    mocker.patch('__builtin__.open')
  else:
    mocker.patch('builtins.open')
  mocker.patch('DIRAC.Interfaces.API.Dirac.gConfig', new=confMock)
  tempMock = mocker.patch('DIRAC.Interfaces.API.Dirac.tempfile')
  tempMock.mkdtemp.return_value = 'tempFolder'
  shMock = mocker.patch('DIRAC.Interfaces.API.Dirac.shutil', new=MagicMock(name="Shutil"))
  sysMock = mocker.patch('DIRAC.Interfaces.API.Dirac.systemCall')
  sysMock.return_value = S_OK([0, 'No output', 'No errors'])
  dirac.getFile = MagicMock(return_value=S_OK())
  ret = dirac.runLocal(job)
  LOG.info("dirac log calls: %s", dirac.log.call_args_list)
  LOG.info("CallStack: %s", pformat(ret.get('CallStack', {})))
  try:
    assert sysMock.call_args_list[0][1]['cmdSeq'] == [
        'dirac-jobexec', 'jobDescription.xml', '-o', 'LogLevel=DEBUG'
    ]
  except AssertionError:
    assert sysMock.call_args_list[0][1]['cmdSeq'] == [
        '/root/dirac/scripts/dirac-jobexec', 'jobDescription.xml', '-o', 'LogLevel=DEBUG'
    ]
  assert ret.get('Message', None) is None
  assert ret['OK']
  assert call('/abspath/absfile.xml', '/pwd/tempFolder/') in shMock.copy.call_args_list
  assert call('/pwd/file_in_pwd.xml', '/pwd/tempFolder/') in shMock.copy.call_args_list
  assert call('/vo/user/i/initial/important.tar.gz') in dirac.getFile.call_args_list
