#!/usr/bin/python
import cgi
import time
import sys
import glob
import os
import re

sys.path.append("py")
import json


def getDataFile(filename, dir=None):
   if dir == None:
      dir = filename
   return "data/" + dir + '/' + filename

def getHeadDB(file):
   return getDataFile(file)+".head.json"

def getLatestDBFilename(file):
   ver = getNextVersion(file)
   if ver.find('.')>=0: # old version format
      return getDBFilename(file, ver)
   ver = int(ver)
   while ver > 1:
      ver-=1
      filename = getDBFilename(file, ver)
      if os.path.exists(filename):
         return filename
   return getOCRDBFilename(file)

def getOCRDBFilename(file):
   return getDataFile(file)+".ocr.json"

def getDBFilename(file, ver):
   if ver == 'ocr':
      return getOCRDBFilename(file)
   return getDataFile(file) + '-' + str(ver) + '.json'

def getVersionFromFilename(filename):
   if filename.rfind('ocr.json')>=0:
      return 'ocr'
   dotpos = filename.rfind('.')
   if dotpos < 0:
      return filename[filename.rfind('-')+1:]
   else:
      return filename[filename.rfind('-')+1:filename.rfind('.')]

def _patch(latestDB, file, logs):
   f = open(latestDB, "r")
   rects = json.read(f.read())
   f.close()
   if 'rects' in rects:
      rects = rects['rects']
   logs = json.read(logs)
   offX = logs['visArea']['x']
   offY = logs['visArea']['y']
   for log in logs['log']:
      r = {'x':offX+log['x'], 'y':offY+log['y'], 
            'width':log['w'], 'height':log['h'], 'text':log['val']}
      if log['id'] == 'new':
         if log['val'] != "":
            id = len(rects)
            r['new'] = 1
            rects[str(id)] = r
      else:
         if log['val'] == "":
            r['del'] = 1
         rects[str(log['id'])] = r
   return rects

def patch(file, logs, newfile):
   latestDB = getLatestDBFilename(file)
   rects = _patch(latestDB, file, logs)
   out = {}
   out['parent'] = getVersionFromFilename(latestDB)
   out['ver'] = getVersionFromFilename(newfile)
   out['rects'] = rects
   f = open(newfile, "w")
   f.write(json.write(out))
   f.close()


def readLatestDB(file):
   f = open(getLatestDBFilename(file), "r")
   ret = f.read()
   f.close()
   return ret


def getVisArea(file,ver):
   filename = glob.glob(getDataFile(file)+"-"+ ver +'-*.log')[0]
   f = open(filename,"r")
   logs = json.read(f.read())
   f.close()
   return json.write(logs['visArea'])


def getLogFromVersion(file, ver):
   filename = glob.glob(getDataFile(file)+"-"+ ver +'-*.log')[0]
   f = open(filename,"r")
   logs = f.read()
   f.close()
   return logs

def getLogFromAssignmentId(hitId, dir = '*'):
   flist = glob.glob('data/'+dir+'/*-*.log') #fixme
   for file in flist:
      f = open(file,"r")
      data = json.read(f.read())
      f.close()
      if 'assignment' in data and data['assignment'] == hitId:
         m = re.search('.*/(.*)-(\d+)-\d+\.\d+\.log$', file)
         fname = m.group(1)
         ver = m.group(2)
         return json.write({'file':fname, 'ver':ver})


def getNextVersion(dir, increment=False):
   file = getDataFile("latest-version",dir)
   if os.path.exists(file):
      f = open(file, 'r')
      line =  f.readline().rstrip()
      f.close()
      ver = line
   else:
      ver = "1"
   if increment:
      f = open(file, 'w')
      f.write(str(int(ver)+1))
      f.close()
   return ver

def writelog(dir, txtlog, oldfile, newfile):
   log = json.read(txtlog)
   log['parent'] = getVersionFromFilename(oldfile)
   log['ver'] = getVersionFromFilename(newfile)

   filename = getDataFile( newfile, dir)+ '-' + str(time.time()) + '.log'
   f = open(filename,"w")
   f.write(json.write(log))
   f.close()

def readDB(file, ver):
   filename = getDBFilename(file, ver)
   if os.path.exists(filename):
      f = open(filename,"r")
      ret = f.read()
      f.close()
      return ret
   else:
      txtlog = getLogFromVersion(file, ver)
      log = json.read(txtlog)
      if 'parent' in log:
         latestDB = getDBFilename(file, log['parent'])
      else:
         latestDB = getLatestDBFilename(file)
      rects = _patch(latestDB, file, txtlog)
      out = {}
      out['parent'] = getVersionFromFilename(latestDB)
      out['ver'] = ver
      out['rects'] = rects
      return json.write(out)

def getReviewLog(file):
   filename = getDataFile('reviewLog',file)
   if os.path.exists(filename):
      f = open(filename,"r")
      ret = f.read()
      f.close()
      return json.read(ret)
   else:
      return {'approve':{}, 'reject':{}}

def writeReviewLog(file, log):
   filename = getDataFile('reviewLog',file)
   f = open(filename,"w")
   f.write(json.write(log))
   f.close()

def getDimension(file):
   filename = getDataFile('dimension',file)
   f = open(filename,"r")
   ret = f.read()
   f.close()
   return ret

def reviewSubmission(file, ver, approve, turkLog=None):
   reviewLog = getReviewLog(file)
   if approve == 'yes':
      action = 'approve'
   else:
      action = 'reject'
   if not turkLog:
      turkLog = ver
   reviewLog[action][ver] = turkLog
   writeReviewLog(file, reviewLog)
   if approve == 'no':
      return
   log = getLogFromVersion(file, ver)
   ver = getNextVersion(file, True)
   headDB = getDBFilename(file, ver)
   patch(file, log, headDB)
   


def main():
   form = cgi.FieldStorage()
   FromTurk = False
   ApproveAll = False
   if 'fromTurk' in form:
      FromTurk = True
   if 'key' in form and form['key'].value == 'UIDER':
      ApproveAll = True

   if 'approve' in form:
      if 'assignment' in form:
         jFileVer = getLogFromAssignmentId(form['assignment'].value, form['db'].value)
         FileVer = json.read(jFileVer)
         ver = FileVer['ver']
      else:
         ver = form['ver'].value
      reviewSubmission(form['db'].value, ver, form['approve'].value)
      print "You answer \"" + form['approve'].value + '\" has been saved.'
      return
   if "assignment" in form:
      file = '*'
      if 'db' in form:
         file = form['db'].value
      print getLogFromAssignmentId(form['assignment'].value, file)
      return
   if "db" in form:
      if 'dimension' in form:
         print getDimension(form['db'].value)
         return
      if "ver" in form:
         if 'visArea' in form:
            print getVisArea(form['db'].value,form['ver'].value)
         else:
            print readDB(form['db'].value, form['ver'].value)
      else:
         print readLatestDB(form['db'].value)
      return
   if not "file" in form:
      print "error"
      return
   dir = form['file'].value
   newVersion = str(getNextVersion(dir,True))
   newfile = dir + '-' + newVersion
   latestDB = getLatestDBFilename(dir)
   writelog(dir, form['log'].value, latestDB, newfile)
   if not FromTurk and ApproveAll:
      print "approved"
      reviewSubmission(dir, newVersion, "yes")
   print "saved!"

print "Content-type: text/html\n\n"

#try:
#   main()
#except Exception,e:
#   print "failed " + str(e)

main()
