from __future__ import print_function
import argparse
import os
import glob
from time import gmtime, strftime, time, sleep
from erp5.util import taskdistribution


class DummyTestResult:

  class DummyTestResultLine:

    def stop(self, duration, stdout='', **kw):
      print('stop:')
      print('\n' + stdout)
      print('stop: %s' % (kw,))
      print('Ran in %.3fs' % duration)

  done = 0

  def __init__(self, test_name_list):
    print("init: Tests to run: %s" % (','.join(test_name_list)))
    self.test_name_list = test_name_list

  def start(self):
    test_result_line = self.DummyTestResultLine()
    try:
      test_result_line.name = self.test_name_list[self.done]
    except IndexError:
      return
    self.done += 1
    print("start: %s" % (test_result_line.name,))
    return test_result_line


def main():
  parser = argparse.ArgumentParser(description='Run a test suite.')
  parser.add_argument('--test_suite', help='The test suite name')
  parser.add_argument('--test_suite_title', help='The test suite title')
  parser.add_argument('--test_node_title', help='The test node title')
  parser.add_argument('--project_title', help='The project title')
  parser.add_argument('--revision', help='The revision to test',
                      default='dummy_revision')
  parser.add_argument('--node_quantity', type=int,
                      help='Number of CPUs to use for the VM')
  parser.add_argument('--master_url',
                      help='The Url of Master controlling test suites')
  # SlapOS and ERP5TestNode specific
  parser.add_argument(
      '--partition_path',
      help="Path of a partition",
      default=os.path.abspath(os.getcwd()))
  parser.add_argument(
      '--test_reference',
      help="Reference of the test",
      default="missing"
  )

  args = parser.parse_args()
  test_list = [args.test_reference]
  test_title = args.test_suite_title or args.test_suite
  if args.master_url:
    tool = taskdistribution.TaskDistributionTool(args.master_url)
    test_result = tool.createTestResult(args.revision,
                                        test_list,
                                        args.test_node_title,
                                        test_title=test_title,
                                        project_title=args.project_title)
    if test_result is None:
      return
  else:
    test_result = DummyTestResult(test_list)

  while 1:
    test_result_line = test_result.start()
    if not test_result_line:
      break
    status_dict = {'command': 'file not found'}

    # find test result, wait 10h
    sleep_time = 10
    try_amount = (3600 * 10) / sleep_time
    try_num = 1
    start = time()
    result_found = False
    while 1:
      finished = False
      try_info = 'Try %s/%s.' % (try_num, try_amount)
      print(try_info + ' Waiting for data.')
      result_list = glob.glob(
          os.path.join(
              args.partition_path,
              '..',
              '*',
              'srv',
              'public',
              'test-script-result',
          ))
      if len(result_list) > 0:
        print(try_info + ' Data directory found, looking for results.')
        result_path = result_list[0]
        result_file_list = list((os.path.join(dirname, filename)
           for dirname, dirnames, filenames in os.walk(result_path)
           for filename in filenames
           ))
        if len(result_file_list):
          print(try_info + ' No result posted, will check next try.')
        for result_file in result_file_list:
          print(try_info + ' Data found.')
          result_found = True
          result_file = os.path.abspath(result_file)
          status_dict['command'] = result_file
          result = open(result_file).read()
          # remove result, as it is not required anymore
          os.unlink(result_file)
          print(try_info + ' Analysis of result %r:' % (result_file,))
          print(try_info + ' ' + result)
          status_dict['stderr'] = result
          if 'FATAL: all hosts have already failed -- aborting' in result:
            # failed
            status_dict.update(
                test_count=1,
                skip_count=0,
                failure_count=1,
                error_count=0
            )
            finished = False
            status_dict['stdout'] = 'Build not yet successful.'
            print(try_info + ' %r: Found not yet finished run.' % (result_file,))
          elif "\"msg\": \"[u'Build successful, connect to:', u'" in result:
            # success
            status_dict.update(
                test_count=1,
                skip_count=0,
                failure_count=0,
                error_count=0
            )
            finished = True
            print(try_info + ' %r: Found finished successful run.' % (result_file,))
            status_dict['stdout'] = 'Build successful.'
            break
          else:
            # unknown
            status_dict.update(
                test_count=1,
                skip_count=0,
                failure_count=0,
                error_count=1
            )
            status_dict['stdout'] = \
                'Cannot find success nor failure result in the output'
            print(try_info + ' %r: Found unknown run.' % (result_file,))
            finished = False
      if finished:
        break
      if try_num > try_amount:
        msg = try_info + ' Time exceeded, success not found.'
        print(msg)
        status_dict['stderr'] = msg
        break
      try_num += 1
      sleep(10)
    if not result_found:
      status_dict['stdout'] = 'Test timed out and no result found.'
      status_dict.update(
          test_count=0,
          skip_count=0,
          failure_count=0,
          error_count=0
      )
    end = time()

    test_result_line.stop(
        date=strftime("%Y/%m/%d %H:%M:%S", gmtime(end)),
        duration=end - start,
        **status_dict)

if __name__ == "__main__":
    main()
