""" In the Classification download, the user's responses to each task are recorded in a field called
'annotations' (including those of experts and those tagged "TRUE" for being gold standard responses.
The field is a JSON string. When loaded into Python using the json.loads() function from import json,
it becomes a dictionary of dictionaries of form {{....}, {.....}, {....}} with a dictionary for each
task the user is required to complete, in the order completed.
The form of the individual dictionaries for the tasks depends very much on what type of task it is -
a question, drawing tool, transcription or survey task.  This set of scripts are for transcription tasks,
which have the form {"task":"TX", "task_label":"instructions the users saw", "value":"text entered"}.
For a single text entry field this is pretty simple, especially if one knows which of
the blocks in annotations we are dealing with. Even without that we can find the correct task because
we know the wording of the instruction text.  Due to the way the project builder can be assembled, it is
unlikely tasks are numbered in the order completed, and with the conditional branching allowed, tasks are
not even in the same order in every response.
Transcriptions are difficult to aggregate. Unless multiple volunteers input the exact same thing, down to
capitalization, spacing and punctuation, simple conditional matching is inadequate and some sort of reconciliation
between the multiple answers must be done.  This problem has been solved and we need to get the data from your
specific project into a format that can use Notes From Nature's code to reconcile the responses.
See https://github.com/juliema/label_reconciliations
It is not a trivial task to set up to use their code - it requires a number of additional python packages be
installed and familiarity with passing arguments to the main module at execution. See the readme on this topic.
While it was written specifically for their somewhat customized Zooniverse interface it has the ability to
reconcile appropriately prepared csv files. These Blocks below break out the classification record so each
text which is to be reconciled with other volunteers entries is in a field by itself with a unique field name
in a csv file suitable to input into nfn's reconcile.py.

The following blocks are intended to prepare the classification records generated by various transcription tasks
available in the project builder in a format that can be utilized by nfn's software."""

#  ___________________________________________________________________________________________________________

#Block 1 Simple transcription tasks - one instruction results in one text block NOT using metadata tags


    #  First add a output field to the file-name list and writer list with value transcribed_text_X for each
        # simple transcription task in the project.
        #  Note, the field_name can be anything you want though often it is some snippet of the instruction.

    #  Secondly add this block below to the body of the frame (see demos) and ensure the line
                annotations = json.loads(row['annotations']) # is not commented out


                transcription_text_1 = ''
                transcription_text_2 = ''
                #...
                transcription_text_N = ''

                for task in annotations:
                    try:
                        if 'snippet of transcription instruction 1' in task['task_label']:
                            if task['value'] is not None:
                                transcription_text_1 = str(task['value'])
                    except KeyError:
                        continue
                    try:
                        if 'snippet of transcription instruction 2' in task['task_label']:
                            if task['value'] is not None:
                                transcription_text_2 = str(task['value'])
                    except KeyError:
                        continue
                    #....
                    try:
                        if 'snippet of transcription instruction N' in task['task_label']:
                            if task['value'] is not None:
                                transcription_text_N = str(task['value'])
                    except KeyError:
                        continue

#  Repeat this block with unique variable names replacing 'transcription_text_N' for each transcription task in
#  the workflow for which you want the transcribed text in the output file. Assign unique field names in the
#  list of fieldnames and in the writer statement and set their values to the appropriate variable names replacing
#  transcription_text_N. This will result in each transcription residing in a defined field in a csv file suitable
#  for use with the csv file option of the nfn reconcile.py argument list.

#________________________________________________________________________________________________________________
# Block 2 and Block 3:  Drawing tasks which uses one tool type such as the rectangle to mark or highlight text in
# a document which is then transcribed in a sub-task of each drawing/mark. Here we need to separate the use of
# each drawing tool into the drawing/location part, and the transcription itself with each part in its own field
# in a csv file.

# For Block 2 only ONE use of each tool colour is allowed but several tools may be used.  It is only useful if there
# is only one obvious block of text to mark and transcribe in the image for each drawing tool.  If multiple uses
# for each tool are allowed, this analysis would be much more difficult since we would not know how many field names
# and columns to set up to handle all the possible locations and transcriptions. Further we would not know what
# order the drawings were made, and which to reconcile without analysing their locations in the text.  Block 3 below
# handles the case where a fixed number of uses of one tool (eg one colour of rectangle for instance) are allowed
# and the locations can be simply ordered from top to bottom of the image. To match locations which are not simple
# to group or order by vertical position only, we would need to aggregate over the various user classifications
# for a subject, find common locations and group the transcriptions to reconcile.  My intention is to explore this
# in future Aggregation techniques.

# Note:  these blocks assume the rectangle is used as the marker but any of the tool types could be used eg points,
# circles, ellipses - in that case modify parameters (x, y, etc) in the drawing and the output list (see the
# function definitions in Block 3 of flatten_class_drawing.py. for the required lists.)

# Block 2   ONE use only of multiple tools (colours) to mark different things to be transcribed as sub-tasks
# for each tool.

    # First add appropriate field names to the list of output field names and to the writer, and assign them
        #  the values drawings_X or transcription_X.  Each tool (ie number or colour) will have a separate field name
        #  and column for the marker location and another for the corresponding transcription.

    # Secondly add this block below to the body of the frame  see demos and ensure the line
                annotations = json.loads(row['annotations']) # is not commented outThird


                #  reset the drawings and transcriptions in case there are no marks or transcriptions made.
                drawings_0 = []
                transcription_0 = ''
                drawings_1 = []
                transcription_1 = ''
                #....
                drawings_N = []
                transcription_N = ''
                for task in annotations: # this for loop can be shared with other drawing or question blocks
                    try:
                        if 'drawing/marking task snippet' in task['task_label']:
                            for drawing_object in task['value']:
                                if drawing_object['x'] is not None:
                                    # round to desired accuracy in pixels (0 or 1 decimal is about optimum)
                                    x = round(drawing_object['x'], 0)
                                    y = round(drawing_object['y'], 0)
                                    w = round(drawing_object['width'], 0)
                                    h = round(drawing_object['height'], 0)
                                    #  Modify these lines as needed (these are for a rectangle)
                                    #  based on the tool type in use and the parameters for that tool. Also add/
                                    #  modify the the parameters in the output lists below.
                                    if drawing_object['tool'] == 0:
                                        drawings_0 = json.dumps([x, y, w, h, 'labels_0'])
                                        transcription_0 = drawing_object['details']
                                    if drawing_object['tool'] == 1:
                                        drawings_1 = json.dumps([x, y, w, h, 'label_1'])
                                        transcription_1 = drawing_object['details']
                                    #.....
                                    if drawing_object['tool'] == N:
                                        drawings_N = json.dumps([x, y, w, h, 'label_N'])
                                        transcription_N = drawing_object['details'][value]

                    except KeyError:
                        continue
#  _________________________________________________________________________________________________________________

# Block 3 One tool (type and colour) used a known maximum number of times on the page.  Each use must be
# separately placed from top to bottom so that a simple sort by vertical location places each drawing and its
# sub-task transcription in the appropriate output column. (example - sequential entries such as logs or diaries)

# As the Maximum allowed number of drawings per image is increased, the larger the output file and the more empty
# fields will be included since 2 columns are always defined for each allowed usage of the tool.

    # First add appropriate 2N field names to the list of output field names and to the writer, and assign them
        #  the values drawings[X] or transcriptions[X]. The value X will start at 0 for the uppermost mark and
        #  increase down the page to N-1 for the last mark that will be handles by this script.
        #  Example :
                                 'first_date_location': drawings[0],
                                 'first_date_transcribed': transcriptions[0],
        #  Each tool USAGE must have a separate field name and column for the marker location and another for the
        #  corresponding transcription.  Set up field names for the maximum number of usages allowed in the project
        #  builder for the tool, or as many as you expect to have.  Additional marks will simply be ignored.

    # Secondly add this line to the area of the frame where variables are given initial values (below line i = 0)
    n = N  # where N is an integer equal to the maximum number of drawings per image that this script can handle

    # Third - add this block in the main area of the frame within the iteration loop over the classification
        # records and assure the line
                annotations = json.loads(row['annotations']) # is not commented out


                #  reset the drawings and transcriptions in case there are no marks or transcriptions made.
                drawings = [[] for d in range(0, n)]
                transcriptions = ['' for t in range(0, n)]

                for task in annotations:  # this for loop can be shared with other drawing or question blocks
                    try:
                        if 'drawing/marking task snippet' in task['task_label']:
                            #  use a decorate-sort-undecorate to order the drawings from the top of the page to
                            #  the bottom no matter what order they were drawn in.
                            decorate = [(item['y'], item) for item in task['value']]
                            decorate.sort()
                            undecorate = [item[1] for item in decorate]

                            for drawing in range(0, n):  #  N is the maximum number of uses allowed
                                try:
                                    if undecorate[drawing] is not None:
                                        drawing_object = undecorate[drawing]
                                        # round to desired accuracy in pixels (0 or 1 decimal is about optimum)
                                        x = round(drawing_object['x'], 0)
                                        y = round(drawing_object['y'], 0)
                                        w = round(drawing_object['width'], 0)
                                        h = round(drawing_object['height'], 0)
                                        drawings[drawing] = json.dumps([x, y, w, h])
                                        try:
                                            transcriptions[drawing] = drawing_object['details']['value']
                                        except IndexError:
                                            transcriptions[drawing] = ''
                                except IndexError:
                                    drawings[drawing] = []
                                    transcriptions[drawing] = ''
                                continue

                    except KeyError:
                        continue

#  _________________________________________________________________________________________________________________
