from wodpy import wod
import glob, time
import numpy as np
import sys, os, json, data.ds
import util.main as main
import pandas, psycopg2
from multiprocessing import Pool

def run(test, profiles):
  '''
  run <test> on a list of <profiles>, return an array summarizing when exceptions were raised
  '''
  qcResults = []
  verbose = []
  exec('from qctests import ' + test)
  for profile in profiles:
    exec('result = ' + test + '.test(profile)')

    #demand tests returned bools:
    for i in result:
      assert isinstance(i, np.bool_), str(i) + ' in test result list is of type ' + str(type(i))

    qcResults.append(np.any(result))
    verbose.append(result)
  return [qcResults, verbose]

def processFile(fName):
  # run each test on each profile, and record its summary & verbose performance
  testResults  = []
  testVerbose  = []
  trueResults  = []
  trueVerbose  = []
  profileIDs   = []
  firstProfile = True
  currentFile  = ''
  f = None

  # keep a list of only the profiles in this thread
  data.ds.threadProfiles = main.extractProfiles([fName])
  data.ds.threadFile     = fName

  for iprofile, pinfo in enumerate(data.ds.threadProfiles):
    if iprofile >= 10:
      continue
    # Load the profile data.
    p, currentFile, f = main.profileData(pinfo, currentFile, f)
    # Check that there are temperature data in the profile, otherwise skip.
    if p.var_index() is None:
      continue
    main.catchFlags(p)
    if np.sum(p.t().mask == False) == 0:
      continue
    # Run each test.    
    for itest, test in enumerate(testNames):
      result = run(test, [p])
      if firstProfile:
        testResults.append(result[0])
        testVerbose.append(result[1])
      else:
        testResults[itest].append(result[0][0])
        testVerbose[itest].append(result[1][0])
    firstProfile = False
    # Read the reference result.
    truth = main.referenceResults([p])
    trueResults.append(truth[0][0])
    trueVerbose.append(truth[1][0])
    profileIDs.append(p.uid())
  # testResults[i][j] now contains a flag indicating the exception raised by test i on profile j
  
  return trueResults, testResults, profileIDs


########################################
# main
########################################

if len(sys.argv)>2:
  # Identify and import tests
  testNames = main.importQC('qctests')
  testNames.sort()
  print('{} quality control checks have been found'.format(len(testNames)))
  testNames = main.checkQCTestRequirements(testNames)
  print('{} quality control checks are able to be run:'.format(len(testNames)))
  for testName in testNames:
    print('  {}'.format(testName))

  # Identify data files and create a profile list.
  filenames = main.readInput('datafiles.json')
  profiles  = main.extractProfiles(filenames)
  data.ds.profiles = profiles
  print('\n{} file(s) will be read containing {} profiles'.format(len(filenames), len(profiles)))

  # Parallel processing.
  print('\nPlease wait while QC is performed\n')
  # old-style----------------------------------
  #processFile.parallel = main.parallel_function(processFile, sys.argv[2])
  #parallel_result = processFile.parallel(filenames)

  # new-style (per file)------------------------
  # pool = Pool(processes=int(sys.argv[2]))
  # parallel_result = []
  # def log_result(result):
  #   '''helper to run as callback after a file is processed'''
  #   parallel_result.append(result)

  # for i in range(len(filenames)):
  #   pool.apply_async(processFile, (filenames[i],), callback = log_result)
  # pool.close()
  # pool.join()
  # new-style (per db row)----------------------
  parallel_result = []
  def log_result(result):
    '''helper to run as callback after a file is processed'''
    parallel_result.append(result)

  def process_row(i):
    '''run all tests on the ith database row'''

    # extract profile
    cur.execute('SELECT * FROM demo LIMIT 1 OFFSET ' + str(i))
    row = cur.fetchall()
    profile = main.mock_wodpy(row[0])
    print profile.uid()

  conn = psycopg2.connect("dbname='root' user='root'")
  cur = conn.cursor()
  cur.execute('SELECT COUNT(*) FROM demo')
  nRows = cur.fetchall()[0][0]

  # launch async processes
  pool = Pool(processes=int(sys.argv[2]))
  for i in range(10):
    pool.apply_async(process_row, (i,), callback = log_result)
  pool.close()
  pool.join()
  
  


  # -------------------------------------------

  # # Recombine results
  # truth, results, profileIDs = main.combineArrays(parallel_result)

  # # Print summary statistics and write output file.
  # main.printSummary(truth, results, testNames)
  # main.generateCSV(truth, results, testNames, profileIDs, sys.argv[1])
else:
  print 'Please add command line arguments to name your output file and set parallelization:'
  print 'python AutoQC myFile 4'
  print 'will result in output written to results-myFile.csv, and will run the calculation parallelized across 4 cores.'

@@ -1155,46 +1155,8 @@
 s):%0A
-    if iprofile %3E= 10:%0A      continue%0A
     
@@ -4171,10 +4171,13 @@
 nge(
-10
+nRows
 ):%0A 

remove a couple of hacks