# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

"""
Refactor the stuff that sets up and tears down the test database details
"""
import datetime as dt
import logging
import os
import time
import psycopg2
import socorro.unittest.testlib.createJsonDumpStore as createJDS

from socorro.lib.datetimeutil import utc_now

def datetimeNow(cursor):
  cursor.execute("SELECT LOCALTIMESTAMP(6)")
  return cursor.fetchone()[0]

def fillProcessorTable(cursor, processorCount, stamp=None, processorMap = {},logger = None):
  """
  Puts some entries into the processor table.
  Also creates priority_jobs_NNN for each processor id, unless that table exists
  Given a map of id->timestamp, sets the lastseendatetime for each successive processor to that stamp
  (Ignores ids generated by the count or in the processorMap, and uses database's serial id generator)
  """
  if not logger:
    logger = logging.getLogger()

  if not stamp: stamp = utc_now()
  if not processorCount and not processorMap: return
  sql = "INSERT INTO processors (name,startdatetime,lastseendatetime) VALUES (%s,%s,%s);"
  data = []
  if processorMap:
    data.extend([('test_%d'%(id),stamp,processorMap.get(id,stamp)) for id in processorMap.keys() ])
  else:
    data.extend([('test_%d'%(x),stamp, stamp) for x in range(1,processorCount+1) ])
  try:
    cursor.executemany(sql,data)
    cursor.connection.commit()

    sql = "SELECT id from processors;"
    cursor.execute(sql)
    allIds = cursor.fetchall()
    cursor.connection.rollback()
    sql = "CREATE TABLE priority_jobs_%s (uuid varchar(50) not null primary key);"
    for tup in allIds:
      try:
        cursor.execute(sql%(tup[0]))
        cursor.connection.commit()
      except psycopg2.ProgrammingError:
        cursor.connection.rollback()
  finally:
    cursor.connection.rollback()

def moreUuid():
  data = [ x for x in createJDS.jsonFileData.keys() ] # fixed order
  jdsIndex = 0
  hex4 = 'dead'
  currentHex = 0
  while True:
    if 0xffff == currentHex: currentHex = 0
    if jdsIndex >= len(data):
      jdsIndex = 0
      currentHex += 1
      if 0xdead == currentHex : currentHex += 1
      hex4 = "%04x"%currentHex
    yield data[jdsIndex].replace('dead',hex4)
    jdsIndex += 1

def makeJobDetails(idsMapToCounts):
  """
  Generate some bogus uuid and path data
  """
  data = []
  gen = moreUuid()
  for id in idsMapToCounts.keys():
    for x in range(idsMapToCounts[id]):
      uuid = gen.next()
      data.append(("/hmm/%s/%s/%s"%(uuid[:2],uuid[2:4],uuid),uuid,id,))
  return data

def addSomeJobs(cursor,idsMapToCounts, logger = None):
  """
  Insert the requested rows into jobs table.
  idsMapToCounts: id:countOfjobsForProcessorWithThisId
    BEWARE: The ids must be actual ids from the processors table or this will fail.
  returns list of the inserted job details
  """
  if not logger:
    logger = logging.getLogger()
  logger.debug("ADDING: %s"%(str(idsMapToCounts)))
  data = makeJobDetails(idsMapToCounts)
  sql = "INSERT INTO jobs (pathname,uuid,owner) VALUES (%s,%s,%s)"
  try:
    cursor.executemany(sql,data)
    cursor.connection.commit()
  except Exception,x:
    logger.error("Failed to addSomeJobs(%s): %s",str(idsMapToCounts),x)
    cursor.connection.rollback()
    raise x
  return data

def setPriority(cursor,jobIds,priorityTableName=None):
  """
  if priorityTableName: for each id in jobIds, insert row in that table holding the uuid of that job
  otherwise, set the job.priority column in the jobs table
    BEWARE: The job ids must be actual ids from the jobs table or this will quietly fail to do anything usefuld
  """
  if not jobIds: return
  wherePart = 'WHERE id IN (%s)'%(', '.join((str(x) for x in jobIds)))
  if priorityTableName:
    sql = "INSERT INTO %s (uuid) SELECT uuid FROM jobs %s"%(priorityTableName,wherePart)
  else:
    sql = "UPDATE jobs SET priority = 1 %s"%(wherePart)
  cursor.execute(sql)
  cursor.connection.commit()

processingDays = None
productDimData = None

signatureData = [
  'NPSWF32.dll@0x15a4bf',
  'RtlpCoalesceFreeBlocks',
  'NPSWF32.dll@0x13b4c2',
  'nsCycleCollector::MarkRoots(GCGraphBuilder&)',
  'arena_dalloc_small | arena_dalloc',
  'kernel32.dll@0xb728',
  'RuleHash_ClassTable_GetKey',
  'SGPrxy.dll@0x258e',
  'GoogleDesktopMozilla.dll@0x54da',
  'ntdll.dll@0x19c2f',
  'user32.dll@0x8815',
  'JS_TraceChildren',
  'NPSWF32.dll@0x2166f3',
  'nanojit::Assembler::pageReset()',
  'nsEventListenerManager::Release()',
  'GraphWalker::DoWalk(nsDeque&)',
  'nsFrame::BoxReflow(nsBoxLayoutState&, nsPresContext*, nsHTMLReflowMetrics&, nsIRenderingContext*, int, int, int, int, int)',
  'NPSWF32.dll@0x172a4e',
  'NPSWF32.dll@0x20a8db',
  '@0x0',
  'NPSWF32.dll@0x2571',
  'Flash Player@0x91bd0',
  'NPSWF32.dll@0xbbff7',
  'AutoCXPusher::AutoCXPusher(JSContext*)',
  'nsChromeTreeOwner::GetInterface(nsID const&, void**)',
  'msvcr80.dll@0xf880',
  'PR_EnumerateAddrInfo',
  'nppl3260.dll@0x54bb',
   'user32.dll@0x1f793',
  'js_MonitorLoopEdge(JSContext*, unsigned int&)',
  'nsGenericElement::cycleCollection::Traverse(void*, nsCycleCollectionTraversalCallback&)',
  'ntdll.dll@0x10a19',
  'js_TraceObject',
  'NPSWF32.dll@0x5b2c8',
  'nsSocketTransport::OnSocketEvent(unsigned int, unsigned int, nsISupports*)',
  'TraceRecorder::emitIf(unsigned char*, bool, nanojit::LIns*)',
  'nsCOMPtr_base::~nsCOMPtr_base()',
  'nsHttpChannel::Release()',
  'morkRowObject::CloseRowObject(morkEnv*)',
  'NPSWF32.dll@0x1c791a',
  'isalloc',
  'user32.dll@0x11911',
  'NPSWF32.dll@0xce422',
  'nsFormFillController::SetPopupOpen',
  'nsDocShell::EnsureContentViewer()',
  'XPCCallContext::XPCCallContext(XPCContext::LangType, JSContext*, JSObject*, JSObject*, int, unsigned int, int*, int*)',
  'NPSWF32.dll@0x2cc09a',
  'libnssutil3.dylib@0x59bf',
  'memmove',
  'wcslen',
  'nppl3260.dll@0x4341',
  'nsBaseWidget::RemoveChild(nsIWidget*)',
  'JS_RemoveRootRT',
  'arena_dalloc_small',
  'nsPluginHostImpl::TrySetUpPluginInstance(char const*, nsIURI*, nsIPluginInstanceOwner*)',
  'nsCOMPtr_base::assign_from_qi(nsQueryInterface, nsID const&)',
  'NPSWF32.dll@0x3f245',
  'NPSWF32.dll@0x1c6510',
  'xul.dll@0x326f0d',
  'GoogleDesktopMozilla.dll@0x56bc',
  'js3250.dll@0x68bec',
  'arena_chunk_init',
  'PL_DHashTableOperate',
  'nsBaseWidget::Destroy()',
  'closeAudio',
  'RaiseException',
  'js_Interpret',
  'js_GetGCThingTraceKind',
  'nsDocShell::SetupNewViewer(nsIContentViewer*)',
  'iml32.dll@0x10efb',
  'UserCallWinProcCheckWow',
  'nsWindow::GetParentWindow(int)',
  'ntdll.dll@0xe514',
  'nsPluginInstancePeerImpl::GetDOMElement(nsIDOMElement**)',
  'nsStyleSet::FileRules(int (*)(nsIStyleRuleProcessor*, void*), RuleProcessorData*)',
  'user32.dll@0x1f793',
  'memcpy | fillInCell',
  'Flash_EnforceLocalSecurity',
  'objc_msgSend | IdleTimerVector',
  'msvcrt.dll@0x37fd4',
  'RtlpWaitForCriticalSection',
  'NPSWF32.dll@0x7c043',
  'nsGlobalWindow::cycleCollection::UnmarkPurple(nsISupports*)',
  'xpcom_core.dll@0x31b7a',
  'nsXPConnect::Traverse(void*, nsCycleCollectionTraversalCallback&)',
  '@0x61636f6c',
  'NPSWF32.dll@0x3d447',
  'fastcopy_I',
  'NPSWF32.dll@0xa7edc',
  'GCGraphBuilder::NoteXPCOMChild(nsISupports*)',
  'kernel32.dll@0x12afb',
  'DTToolbarFF.dll@0x4bc19',
  '_PR_MD_SEND',
  'nsXULDocument::OnStreamComplete(nsIStreamLoader*, nsISupports*, unsigned int, unsigned int, unsigned char const*)',
  '6199445655488030487637489004489057483483495843503286493177488015467495487215487445487563488802',
  'nsMimeTypeArray::GetMimeTypes()',
  'dtoa',
  'nsScriptLoader::StartLoad(nsScriptLoadRequest*, nsAString_internal const&)',
  'ntdll.dll@0x43387',
  'nsCycleCollectingAutoRefCnt::decr(nsISupports*)',
  'CFReadStreamGetStatus',
  'GoogleDesktopMozilla.dll@0x5500',
  'NPSWF32.dll@0x143c15',
  'nsXHREventTarget::GetParentObject(nsIScriptGlobalObject**)',
  'NPSWF32.dll@0x1c6168',
  'NPSWF32.dll@0x1b9cf9',
  'NSSRWLock_LockRead_Util',
  'NoteJSChild',
  'NPSWF32.dll@0x77540',
  'GoogleDesktopMozilla.dll@0x5512',
  'radhslib.dll@0x3b6f',
  'BtwVdpCapFilter.dll@0xa345',
  'ntdll.dll@0x100b',
  'avgssff.dll@0x9ba3',
  'msvcr80.dll@0xf870',
  'js_NewGCThing',
  'ntdll.dll@0x1b21a',
  'ScanBlackWalker::ShouldVisitNode(PtrInfo const*)',
  'nsAutoCompleteController::ClosePopup',
  '_PR_MD_ATOMIC_DECREMENT',
  'fun_trace',
  ]
def genSig(countOfSignatures=7):
  global signatureData
  assert countOfSignatures <= len(signatureData), 'Better be at least %s!, but was %s'%(countOfSignatures,len(signatureData))
  while True:
    for s in signatureData[:countOfSignatures]:
      yield s

def moreUrl(realUrls, count=430):
  if not realUrls:
    while True:
      yield None
  else:
    dirpath = os.path.split(os.path.abspath(__file__))[0]
    # urlLines contains over 9500 lines, many are duplicates (1999 distinct), in random order
    f = None
    try:
      f = open(os.path.join(dirpath,'urlLines.txt'))
      data = []
      if count:
        try:
          for i in range(count):
            line = f.next()
            if line:
              data.append(line.strip())
            else:
              data.append(None)
        except StopIteration:
          pass
      else:
        for line in f:
          if line:
            data.append(line.strip())
          else:
            data.append(None)
    finally:
      if f:
        f.close()
    while True:
      for url in data:
        yield url[:255]

