# THIS FILE IS A PART OF VCStudio
# PYTHON 3

import os
import cairo

#UI modules
from UI import UI_elements
from UI import UI_color

#settings
from settings import talk

#studio
from studio import analytics
from studio import history

def get_list(filepath):
    
    # This fucntion converts text documents. (.progress) into a more machine
    # friendly recursive dict.
    
    # In the original organizer evaluation of the checklist was done separatelly
    # in a different function. Which made it very messy for recursive stuff.
    # I will attemp to combine it. And make it more clean as a result.
    
    checklist = {
        "fraction":0.0, # The percentage of a checklist. From 0.0 to 1.0
        "string":filepath,     
        "editing":False,# Whether the string is during editing. UI.
        "selected":False,# Whether the current task is selected.
        "open":True,    # Whether to draw the suptasks. UI.
        "subtasks":[]   # List of subtastks. (In the same format as the checklist)
        }
    
    
    data = open(filepath)
    data = data.read()
    data = data.split("\n")
    
    # Let's filter out all the comments. Lines starting with #. For some reason
    # in the old organizer. I just thought it wasn't important. LOL. And just
    # started reading from the 10th line. 
    
    # Here is an example of the first 9 lines.
    
    #  1 #### Blender orgainizer checklist format
    #  2 #### INDINTATION (4 SPACES LONG)
    #  3 #### STR means Start date of the ASSET
    #  4 #### FIN means Finish deadline of the asset
    #  5 #### [ ] means that task is on list
    #  6 #### [V] means that tast is finished
    #  7 #### DO NOT USE EMPTY LINES
    #  8 STR 24/02/2020
    #  9 FIN 01/05/2021
    
    # You can see a trace from a very long time ago. From the first versions
    # of the blender organizer. The STR and FIN values. Which are start and
    # deadline of the project.
    
    # I guess we need to filter it out a bit differently. Checking whether a
    # given line starts with a [ or with a number of spaces and [. This will
    # make the file a little more open to editing by hand. Without too much
    # worrying that something will break.
    
    cleandata = []
    
    for line in data:
    
        # So not to mangle the line.
        tmp = line
        while tmp.startswith(" "):
            tmp = tmp[1:]
        
        # Checking
        if tmp.startswith("[ ]") or tmp.startswith("[V]"):
            cleandata.append(line)
    
    # Now since we have the cleandata. We can try to parse it somehow into a
    # checklist thing. For this we need a reqursion. I gonna use a method from
    # the blender-organizer. By running the function with in itself. It's not
    # very wise. I know. In python3 it will give you no more then 996 recursions
    # untill it will declare an error. BUT. It's 996 layers of a subtaks.
    # For now I don't see a need in so many subtasks. Let's think of layers of
    # subtasks as of memory. This laptop has only 8 GB of RAM. I can't put more
    # data into it even if I wanted.
    
    def convert(part, indent=0):
        # If a thing have subtasks it should not even be a checkbox. So trying
        # To evaluate it's fraction by whether it's a [ ] or [V] shoun't be
        # done.
        
        subtask = []
        
        for num, line in enumerate(part):
            
            # Let's get the NEXT line. I'm not kidding. We gonna work with the
            # next line to see whether to count this lines [V]
            
                
            if line[indent:].startswith("["):
                
                thisline = {
                    "fraction":0.0, 
                    "string":line[line.find("]")+2:],     
                    "editing":False,
                    "selected":False, 
                    "open":False,    
                    "subtasks":[]   
                    }
                
                try:
                    nextline = part[num+1]
                except:
                    nextline = ""
                
                if not line[line.find("]")+1] == ".":
                    thisline["open"] = True
                
                if nextline.find("[")-1 <= indent:
                    if line[indent:].startswith("[V]"):
                        thisline["fraction"] = 1.0
                
                else:
                    subpart = []
                    subdent = indent
                    for n, l in enumerate(part[num+1:]):
                        if n == 0:
                            subdent = l.find("[")
                        
                        if l.find("[")-1 <= indent:
                            break
                        
                        else:
                            subpart.append(l)
                    
                    #print(subpart)
                    thisline["subtasks"] = convert(subpart, subdent)
                    
                    fracs = []
                    for task in thisline["subtasks"]:
                        if not task["string"].startswith("#"):
                            fracs.append(task["fraction"])
                    
                    try:
                        thisline["fraction"] = sum(fracs) / len(fracs)
                    except:
                        thisline["fraction"] = 0.0
                    
                    # Sometime it was showing 99% when infect it's 100%
                    if thisline["fraction"] == 0.9999:
                        thisline["fraction"] =  1.0
                    
                    
                subtask.append(thisline)
            
        return subtask
        
        
    checklist["subtasks"] = convert(cleandata) 
    fracs = []
    for task in checklist["subtasks"]:
        if not task["string"].startswith("#"):
            fracs.append(task["fraction"])
    
    try:
        checklist["fraction"] = sum(fracs) / len(fracs)
    except:
        checklist["fraction"] = 0.0
    
    # Sometime it was showing 99% when infect it's 100%
    if checklist["fraction"] == 0.9999:
        checklist["fraction"] =  1.0
    
    
    return checklist 

def get_fraction(win, path):

    ############################################################################
    
    # This function will return a fraction of a given checklist. It will ignore
    # complitelly what is the asset / shot / project the checklist is from.
    
    # For sake of making this function actually somewhat useful, aka not bloated
    # I will use it to cashe the whole checklist data objects. So they could be
    # easily accesable later on. 
    
    # This is usefull so I would not need to create 2 cash data structures. One
    # for fractions and for the checklists them selves.
    
    ############################################################################
    
    
    if path not in win.checklists:
        
        # Let's check if path exists in the project first.
        
        if os.path.exists(win.project+"/"+path):
            win.checklists[path] = get_list(win.project+"/"+path)
        else:
            win.checklists[path] = get_list(path)
        
    
    # Let's now return back the fraction
    
    return win.checklists[path]["fraction"]

def get_task_by_path(tasks, path, p=[]):
    
    ############################################################################
    
    # This function will give the information about a given task from a non
    # recursive URL such as ["Task", "Sub-task", "Sub-task2"]. This will look
    # the recursive list and output the given task. In this case "Sub-task2"
    # with all the information inside it.
    
    ############################################################################
  
    
    for task in tasks:
        
        pa = p.copy()
        pa.append(" "+task["string"])
        
        
        if pa == path:
            return task
        
        if task["subtasks"]:
            t = get_task_by_path(task["subtasks"], path, pa)
            if t:
                return t
        
    return False
                
def filter_tasks(data):
    
    ############################################################################
    
    # This function going to remove all selections and all edits from a given
    # checklist. This is nessesary for being able to select one task without
    # manually deselcting the other. And since the checklist is recursive it's
    # not a trivial task.
    
    ############################################################################
    
    data["selected"] = False
    data["editing"]  = False
    
    if data["subtasks"]:
        for i in data["subtasks"]:
            filter_tasks(i)
    
    
def save(path, data):
    
    ############################################################################
    
    # This funtion will save the checklist into a .progress file. Formatted
    # similarly as in the old Blender-Organizer. But as easy to understand.
    # 
    # NOTE: I will remove some stuff from the file. Mainly the comments in the
    # beginning and the STR and END data. Which are no longer needed in a
    # VCStudio project. 
    #
    # But since some part of Legacy Organizer relies on those, it's not adviced
    # to open the projects that you are planning to work on with Blender-Organizer
    # in VCStudio.
    
    ############################################################################    

    
    indent = [0]
    
    lines = []
    
    def writetasks(tasks):
        
        for task in tasks:
            if task["fraction"] and not task["subtasks"]:
                v = "[V]"
            else:
                v = "[ ]"
            
            if task["open"]:
                o = " "
            else:
                o = "."
                
            lines.append(" "*indent[0]+v+o+task["string"])
            
            if task["subtasks"]:
                indent[0] = indent[0] + 4
                writetasks(task["subtasks"])
                indent[0] = indent[0] - 4
                
    writetasks(data["subtasks"])
    
    # Writting to file
    w = open(path, "w")
    
    for i in lines:
        w.write(i+"\n")
    
    w.close()
    
def draw(outlayer, win, path, back="story_editor"):
    
    ############################################################################
    
    # This function will draw the checklists to the screen.
    
    # You probably noticed that there is no x, y, width or height values that
    # you can input. This due to one idea that I have in mind.
    
    # I'm planning to make scheduling a kind of interactive process rather then
    # a boring date selection. Something that's going to be somewhat fun to do.
    
    # The idea is to grab the task and to drug it outside the checklist. Which
    # will call for an analytics window to show up, where you can put the 
    # schedules into a given date. 
    
    # For this reason the checklist should always be in the same spot on the 
    # screen. Which is a (window width) / 4 at the right side. 
    
    ############################################################################
    
    if path not in win.checklists:
        
        # Let's check if path exists in the project first.
        
        if os.path.exists(win.project+"/"+path):
            win.checklists[path] = get_list(win.project+"/"+path)
        elif os.path.exists(win.project+"/rnd"+path):
            win.checklists[path] = get_list(win.project+"/rnd"+path)
        else:
            win.checklists[path] = get_list(path)
    
    
    x = win.current["w"] / 4 * 3 + 10
    y = 10
    width = win.current["w"] / 4 - 20
    height = win.current["h"] - 20
    
    # Now let's make a layer.
    
    # Making the layer
    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
    layer = cairo.Context(surface)
    layer.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
    
    # Clip
    UI_elements.roundrect(layer, win,
        0,
        0, 
        width,
        height,
        10,
        fill=False)
    layer.clip()
    
    
    
    # Checklist icon.
    UI_color.set(layer, win, "node_background")
    UI_elements.roundrect(layer, win,
        0,
        0, 
        width,
        50,
        10)
    
    UI_elements.image(layer, win, 
            "settings/themes/"+win.settings["Theme"]+"/icons/checklist.png",
            5, 5, 40, 40)
    
    # Fraction
                
    fraction = win.checklists[path]["fraction"]
    
    UI_color.set(layer, win, "progress_background")
    UI_elements.roundrect(layer, win,
        50,
        17, 
        width - 60,
        0,
        7)
    
    UI_color.set(layer, win, "progress_active")
    UI_elements.roundrect(layer, win,
        50,
        17, 
        (width - 60 )*fraction,
        0,
        7)
    
    # Clip
    UI_elements.roundrect(layer, win,
        0,
        60, 
        width,
        height,
        10,
        fill=False)
    layer.clip()
    
    
    ###########################################################################
    
    # NOW THIS IS THE HARD RECURSION PART! THERE IS GOING TO BE SOME REDIC!
    
    ###########################################################################
    
    tileX = 0
    current_Y = 70
    
    # There is some bullshit regarding the Global variables. I gonna do a bit
    # trickier. Since lists are only links to lists. Let's do this.
    
    cXY = [tileX, current_Y]
    
    if "checklist" not in win.scroll:
        win.scroll["checklist"] = 0
    
    if "moving_task_now" not in win.current:
        win.current["moving_task_now"] = False
    
    def draw_tasks(tasks, cXY, schedulep):
        
        
        
        #########################################
        #                                       #
        #    THIS IS THE RECURSIVE FUNCTION     #
        #                                       #
        #########################################
        
        # I will try to explain what is going on here. But it will require me
        # understanding the code myself. And it's a bit redic. There was a hell
        # of a lot of copy-paste, edit value, continue.
        
        for num , task in enumerate(tasks):
            
            # This is the code that will be done for each task in the list. Or
            # subtask if a task have them.
            
            # Let's get a schedule path. A folder like structure. 
            # Exacmple:
            
            # Instead of:
            #   Task
            #       Sub-Task
            #           Sub-Task 2
            
            # We get:
            # [" Task", " Sub-Task", " Sub-Task 2"]
            
            schedulepath = schedulep.copy()
            schedulepath.append(" "+task["string"])
            
            
            ###### SCHEDULING STUFF BACKWARD ######
            
            # This is a set of stuff to make schedules work with checklists.
            
            if "schedule_task_selected" not in win.current:
                win.current["schedule_task_selected"] = False
                
            if win.current["schedule_task_selected"] and win.cur == win.current["schedule_task_selected"][-1]:
                csl = win.current["schedule_task_selected"][0][0][4]
                
                print(win.current["schedule_task_selected"])
                
                if " "+task["string"] in csl and not task["open"]:
                    task["open"] = True
                
                if schedulepath == csl and not task["selected"]:
                    filter_tasks(win.checklists[path])
                    task["selected"] = True
                    win.scroll["checklist"] = 0 - cXY[1] + height/2
                    
            
            #### DELETE SHORT KEY ####
            
            # There is probably a reason to put it here. Probably something
            # breaks if you put it anywhere else. IDK actually. Test it. I
            # don't remember
            
            if 65535 in win.current["keys"] and task["selected"] and not win.current["schedule_task_selected"]:
                del tasks[num]
                win.current["keys"] = []
            
                # Saving
                save(path, win.checklists[path])
                win.checklists = {}
                win.assets = {}
                win.analytics = analytics.load(win.project)
            
            #### THE GRABBING FUNCTION ####
            
            # This is the activation of the grab tool. It uses the same 
            # win.current["tool"] = "grab" as the story editor. Because it makes
            # sense to reuse it if it already exists. For sake of conviniense.
            
            # It doesn't mean that it uses the same code. It's a bit different. 
            # due to the nature of lists vs free positioning items.
            
            # Now let's set up a few positional variables. So I could move the tasks
            # while moving the currently selected task. And in the same time will not
            # screw the data. 
            
            # So I copy the X and the Y locations like this.
            
            sx = cXY[0] 
            sy = win.scroll["checklist"] + cXY[1]
            
            grabY = 40
            if task["subtasks"]:
                grabY = 60
            
            # Grab
            if win.current["LMB"]\
            and int(win.current["LMB"][0]) in range(int(x+sx), int(x+sx+width))\
            and int(win.current["LMB"][1]) in range(int(y+sy), int(y+sy+grabY))\
            and win.current["tool"] == "selection"\
            and int(win.current["LMB"][0]) not in range(int(win.current["mx"]-2), int(win.current["mx"]+2))\
            and int(win.current["LMB"][1]) not in range(int(win.current["my"]-2), int(win.current["my"]+2)):
                
                # So here we set up the grab tool and creating a little variable.
                # This variable (moving_task_now) will consist of 2 parts on release.
                
                # 1. The entire task ( with subtasks ) using pop. Which is not simply
                #    a copy. But also removing the task from the checklist's list.
                
                # 2. The current frame of poping. So to offset insertion for 1 frame.
                #    This insures that you insert the task in the correct spot.
                
                filter_tasks(win.checklists[path])
                task["selected"] = True
                win.current["schedule_task_selected"] = False
                
                win.current["tool"] = "grab"
                win.current["moving_task_now"] = False
            
            # Now let's actually setup the pop. So when the mouse is now pressed, but
            # was on a previous framae, and our current tool is grab.
            
            if not win.current["LMB"] and win.previous["LMB"] and win.current["tool"] == "grab"\
            and task["selected"]:
                
                # We remove the task from the list. And write it to the variable. With 
                # the current frame.
                
                win.current["moving_task_now"] = [tasks.pop(num), win.current["frame"]]
                
           
            
            # Now I can touch the sx and sy without screwing up the cXY or scroll.
            
            thismoving = False # This is going to be True is this is the task that's
                               # moving currently
            somemoving = False # This is going to be True if any task is moving
            someXY = [0,0]     # And this is the mouse position translated to location
                               # of the checklist. (x, y coordinates of the whole 
                               # widget). Or in other words position of the task.
            
            # Then comes some logic to determen those 3 values.
            
            if win.current["tool"] == "grab":
                
                # Okay so here. If grab first we assume that it's some other
                # task. And now currently selected one.
                
                somemoving = True
                someXY = [
                    win.current["mx"]-x,
                    win.current["my"]-y
                    ]
                
                # Now this is the editing of the sx and sy values. To be at
                # the position of the mouse. 
                
                if task["selected"]:
                    
                    # Calculating so the mouse will end up about in the centre
                    # of the task while the task is at motion.
                    
                    sx  =  win.current["mx"] - x - (width - cXY[0])/2
                    sy  =  win.current["my"] - y - 10
                    task["open"] = False
                    thismoving = True
                    somemoving = False
                    
                    # Now if the mouse is outside the frame of the checklist
                    # it will activate the scheduling. 
                    
                    ############################################################
                    #                     SCHEDULING PART                      #
                    ############################################################
                    
                    if win.current["mx"] < x:
                        win.url = "analytics"
                        win.current["grab_data"] = [path, back, win.cur, schedulepath, win.settings["Username"]]
                        win.current["tool"] = "schedule"
                 #      
                #        
               #   
              #                 SEE studio/studio_analyticsLayer.py
             #                   for more details about scheduling
            # 
            
            # And if back into frame it will return to normal grab mode.
            
            elif win.current["tool"] == "schedule" and win.current["mx"] > x:
                win.url = back
                win.current["tool"] = "grab"
            
            ####################################################################
            #                       SCHEDULING PART END                        #
            ####################################################################
            
            
            inside = False
            between = False
            
            if sy-10 < someXY[1] < sy+10 and somemoving and not task["selected"]:
                
                if win.current["moving_task_now"] and win.current["moving_task_now"][1] != win.current["frame"]:
                    tasks.insert(num, win.current["moving_task_now"][0])
                    win.current["tool"] = "selection"
                    win.current["LMB"] = False
                    win.previous["LMB"] = False
                    
                    # Saving
                    save(path, win.checklists[path])
                    win.checklists = {}
                    win.assets = {}
                    win.analytics = analytics.load(win.project)
                    
                elif win.current["LMB"]:
                    
                    for line in range(int(cXY[0]/20)):
                    
                        line = line * 20 + 10
                        
                        UI_color.set(layer, win, "node_background")
                        layer.move_to(line, win.scroll["checklist"] + cXY[1]-10)
                        layer.line_to(line, win.scroll["checklist"] + cXY[1]+40)
                        layer.stroke()
                    
                    cXY[1] = cXY[1] + 50
                    
                    sx = cXY[0]
                    sy = win.scroll["checklist"] + cXY[1]
                    
                    between = True
                    somemoving = False
            
            elif sy < someXY[1] < sy + 40 and somemoving and not task["selected"]:
                
                if win.current["moving_task_now"]  and win.current["moving_task_now"][1] != win.current["frame"]:
                    task["subtasks"].append(win.current["moving_task_now"][0])
                    win.current["tool"] = "selection"
                    win.current["LMB"] = False
                    win.previous["LMB"] = False
                    
                    # Saving
                    save(path, win.checklists[path])
                    win.checklists = {}
                    win.assets = {}
                    win.analytics = analytics.load(win.project)
                    
                elif win.current["LMB"]:
                    inside = True
                
            # Selection
            if win.textactive != "editing_task" and win.current["tool"] == "selection":
                def do():
                    ed = task["selected"] and not task["editing"]
                    filter_tasks(win.checklists[path])
                    win.current["schedule_task_selected"] = False
                    task["selected"] = True
                    if ed:
                        task["editing"] = True
                UI_elements.roundrect(layer, win,
                    sx+40,
                    sy, 
                    width - cXY[0]-40,
                    grabY,
                    10,
                    button=do,
                    offset=[x,y],
                    fill=False)
                layer.stroke()
        
            # Background
            if not task["subtasks"]:
                UI_color.set(layer, win, "node_background")
                if task["string"].startswith("#"):
                    UI_color.set(layer, win, "dark_overdrop")
                UI_elements.roundrect(layer, win,
                    sx,
                    sy, 
                    width - cXY[0],
                    40,
                    10)
                
                if inside:
                    UI_color.set(layer, win, "progress_background")
                    UI_elements.roundrect(layer, win,
                        sx,
                        sy, 
                        width - cXY[0],
                        40,
                        10,
                        fill=False)
                    layer.stroke()
                    
                if task["selected"]:
                    UI_color.set(layer, win, "text_normal")
                    UI_elements.roundrect(layer, win,
                        sx,
                        sy, 
                        width - cXY[0],
                        40,
                        10,
                        fill=False)
                    layer.stroke()
                # Line to see how deep you are in
                
                for line in range(int(cXY[0]/20)):
                    
                    line = line * 20 + 10
                    
                    UI_color.set(layer, win, "node_background")
                    layer.move_to(line, win.scroll["checklist"] + cXY[1]-10)
                    layer.line_to(line, win.scroll["checklist"] + cXY[1]+40)
                    layer.stroke()
                
                if not task["string"].startswith("#"):
                    if task["fraction"]:
                        im = "checked"
                    else:
                        im = "unchecked"
                    
                    # CHECK BUTTON
                    
                    def do():
                        if task["fraction"]:
                            task["fraction"] = 0.0
                            history.record(win, path, "[Un-Checked]", schedulepath)
                        else:
                            task["fraction"] = 1.0
                            history.record(win, path, "[Checked]", schedulepath)
                            
                        # Saving
                        save(path, win.checklists[path])
                        win.checklists = {}
                        win.assets = {}
                        #win.analytics = analytics.load(win.project)
                        
                    UI_elements.roundrect(layer, win,
                        sx,
                        sy, 
                        40,
                        40,
                        10,
                        button=do,
                        icon=im,
                        offset=[x,y])
                
                
            else:
                UI_color.set(layer, win, "node_background")
                if task["string"].startswith("#"):
                    UI_color.set(layer, win, "dark_overdrop")
                UI_elements.roundrect(layer, win,
                    sx,
                    sy, 
                    width - cXY[0],
                    60,
                    10)
                
                if inside:
                    UI_color.set(layer, win, "progress_background")
                    UI_elements.roundrect(layer, win,
                        sx,
                        sy, 
                        width - cXY[0],
                        60,
                        10,
                        fill=False)
                    layer.stroke()
                    
                
                if task["selected"]:
                    UI_color.set(layer, win, "text_normal")
                    UI_elements.roundrect(layer, win,
                        sx,
                        sy, 
                        width - cXY[0],
                        60,
                        10,
                        fill=False)
                    layer.stroke()
                
                # Line to see how deep you are in
                
                for line in range(int(cXY[0]/20)):
                    
                    line = line * 20 + 10
                    
                    UI_color.set(layer, win, "node_background")
                    layer.move_to(line, win.scroll["checklist"] + cXY[1]-10)
                    layer.line_to(line, win.scroll["checklist"] + cXY[1]+60)
                    layer.stroke()
                
                # Fraction
                if not task["string"].startswith("#"):
                    fraction = task["fraction"]
                    
                    UI_color.set(layer, win, "progress_background")
                    UI_elements.roundrect(layer, win,
                        sx+10,
                        sy+45, 
                        width-20 - cXY[0],
                        0,
                        5)
                    
                    UI_color.set(layer, win, "progress_active")
                    UI_elements.roundrect(layer, win,
                        sx+10,
                        sy+45, 
                        (width -20 - cXY[0])*fraction,
                        0,
                        5)
                
                if task["open"]:
                    im = "open"
                else:
                    im = "closed"
                
                def do():
                    task["open"] = not task["open"]
                    win.current["schedule_task_selected"] = False
                    # Saving
                    save(path, win.checklists[path])
                    
                    
                UI_elements.roundrect(layer, win,
                    sx,
                    sy, 
                    40,
                    60,
                    10,
                    button=do,
                    icon=im,
                    offset=[x,y])
               
             
             
                
            # TEXT
            
            # ECS
            if 65307 in win.current["keys"] and task["editing"]:
                
                # It's here because Text entry has it's own ESC
                
                win.textactive = ""
                task["editing"] = False
                del win.text["editing_task"]
                win.current["keys"] = []
                
                # Saving
                save(path, win.checklists[path])
                win.checklists = {}
                win.assets = {}
                win.analytics = analytics.load(win.project)
            
            if not task["editing"]:
                layer.set_font_size(20)
                layer.move_to(
                    sx+50,
                    sy+25
                    )
                if task["string"].startswith("#"):
                    UI_color.set(layer, win, "progress_background")
                    if not task["subtasks"]:
                        layer.move_to(
                            sx+10,
                            sy+25
                            )
                    layer.show_text(task["string"][1:])
                else:
                    UI_color.set(layer, win, "text_normal")
                    layer.show_text(task["string"])
            else:
                
                
                UI_elements.text(layer, win, "editing_task",
                    sx+39,
                    sy, 
                    width - cXY[0] - 40,
                    40,
                    set_text=task["string"],
                    offset=[x,y])
                
                win.textactive = "editing_task"
                
                # Assigning the text
            
                
                def do():
                    task["string"] = win.text["editing_task"]["text"]
                    win.textactive = ""
                    filter_tasks(win.checklists[path])
                    del win.text["editing_task"]
                    
                    # Saving
                    save(path, win.checklists[path])
                
                def button():
                    do()
                    win.checklists = {}
                    win.assets = {}
                    
                UI_elements.roundrect(layer, win, 
                    sx+39  + width - cXY[0] - 80,
                    sy,
                    40,
                    40,
                    10,
                    button=button,
                    icon="ok",
                    tip=talk.text("checked"),
                    offset=[x,y])
                
                # Enter
                if 65293 in win.current["keys"]:
                    button()
                    win.current["keys"] = []
                
                    
                # Tab
                if 65289 in win.current["keys"]:
                    do()
                    tasks.append(            
                            {
                        "fraction":0.0, 
                        "string":"",     
                        "editing":True,
                        "selected":True, 
                        "open":False,    
                        "subtasks":[]   
                        }
                    )
                    win.current["keys"] = []
            
            # RECURSION
            if not thismoving:
                if not task["subtasks"]:
                    cXY[1] = cXY[1] +  50
                else:
                    cXY[1] = cXY[1] +  70
                    
                    cXY[0] = cXY[0] +  20
                    
                    # THERE IS YOUR RECURSION
                    
                    if task["open"]:
                        draw_tasks(task["subtasks"], cXY, schedulepath)
                    
                    cXY[0] = cXY[0] -  20
            
            # Adding subtasks
            
            if ((task["subtasks"] and task["open"] and task["selected"])\
            or (task["selected"] and not task["subtasks"]))\
            and win.textactive != "editing_task"\
            and win.current["tool"] == "selection":
                
                cXY[0] = cXY[0] +  20
                
                def do():
                    task["open"] = True
                    filter_tasks(win.checklists[path])
                    task["subtasks"].append(            
                            {
                        "fraction":0.0, 
                        "string":"",     
                        "editing":True,
                        "selected":True, 
                        "open":False,    
                        "subtasks":[]   
                        }
                    )
                    
                
                UI_elements.roundrect(layer, win,
                    cXY[0],
                    win.scroll["checklist"] + cXY[1], 
                    width - cXY[0],
                    40,
                    10,
                    button=do,
                    icon="new",
                    offset=[x,y])
                
                UI_color.set(layer, win, "progress_background")
                UI_elements.roundrect(layer, win,
                    cXY[0],
                    win.scroll["checklist"] + cXY[1], 
                    width - cXY[0],
                    40,
                    10,
                    fill=False)
                layer.stroke()
                
                layer.set_font_size(20)
                layer.move_to(
                    cXY[0]+50,
                    win.scroll["checklist"] + cXY[1]+25
                    )
                layer.show_text(talk.text("add_new_subtask"))
                
                for line in range(int(cXY[0]/20)):
                    
                    line = line * 20 + 10
                    
                    UI_color.set(layer, win, "node_background")
                    layer.move_to(line, win.scroll["checklist"] + cXY[1]-10)
                    layer.line_to(line, win.scroll["checklist"] + cXY[1]+40)
                    layer.stroke()            
                
                            
                cXY[0] = cXY[0] -  20
                cXY[1] = cXY[1] +  50
                
    schedulepath = []
    draw_tasks(win.checklists[path]["subtasks"], cXY, schedulepath)
    
    # Go to the bottom.
    
    if win.current["tool"] == "grab"\
    and win.current["my"] - y > win.scroll["checklist"] + cXY[1]:
        
        if win.current["moving_task_now"] and win.current["moving_task_now"][1] != win.current["frame"]:
            win.checklists[path]["subtasks"].append(win.current["moving_task_now"][0])
            win.current["tool"] = "selection"
            win.current["LMB"] = False
            win.previous["LMB"] = False
            
            # Saving
            save(path, win.checklists[path])
            win.checklists = {}
            win.assets = {}
            win.analytics = analytics.load(win.project)
       
    
    
    
    # Adding a task.
    if win.textactive != "editing_task"\
    and win.current["tool"] == "selection":
        def do():
            filter_tasks(win.checklists[path])
            win.checklists[path]["subtasks"].append(
                {
                    "fraction":0.0, 
                    "string":"",     
                    "editing":True,
                    "selected":True, 
                    "open":False,    
                    "subtasks":[]   
                    }
                )
        
        UI_elements.roundrect(layer, win,
            cXY[0],
            win.scroll["checklist"] + cXY[1], 
            width - cXY[0],
            40,
            10,
            button=do,
            icon="new",
            offset=[x,y])
        
        UI_color.set(layer, win, "progress_background")
        UI_elements.roundrect(layer, win,
            cXY[0],
            win.scroll["checklist"] + cXY[1], 
            width - cXY[0],
            40,
            10,
            fill=False)
        layer.stroke()
        
        layer.set_font_size(20)
        layer.move_to(
            cXY[0]+50,
            win.scroll["checklist"] + cXY[1]+25
            )
        layer.show_text(talk.text("add_new_task"))
    
    
    
    tileX, current_Y = cXY
    
    # So there would not be jumps of stuff. Let's add heigh to the scroll while
    # in grab.
    if win.current["tool"] == "grab":
        current_Y = current_Y + height
    
        
    
    # Outputting the layer
    outlayer.set_source_surface(surface, x, y)
    outlayer.paint() 
    
    # Scroll
    UI_elements.scroll_area(outlayer, win, "checklist", 
        x+0,
        y+50,
        width, 
        height-50,
        current_Y,
        bar=True,
        mmb=True)