# THIS FILE IS A PART OF VCStudio
# PYTHON 3

import os
import datetime
import threading

# GTK module ( Graphical interface
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import GLib
from gi.repository import Gdk
import cairo

# Own modules
from settings import settings
from settings import oscalls
from settings import talk
from project_manager import pm_project

from studio import analytics
from studio import studio_nodes
from studio import studio_dialogs
from studio import story
from studio import analytics
from studio import schedule

#UI modules
from UI import UI_elements
from UI import UI_color


def layer(win):
    
    ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
    stf = datetime.datetime.now()
    perfStat = []
    ###################################################################
    
    
    # Making the layer
    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, win.current['w'],
                                                      win.current['h'])
    layer = cairo.Context(surface)
    
    
    #text setting
    layer.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
    
    
    ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
    fif = datetime.datetime.now()
    mil  = fif - stf
    perfStat.append([ "Setup", mil.microseconds ])
    stf = datetime.datetime.now()
    ###################################################################
    
    
    UI_color.set(layer, win, "darker_parts")
    UI_elements.roundrect(layer, win,
        50,
        50, 
        win.current["w"] - 100,
        win.current["h"] - 80,
        30)
    
    # Little verion thing in the bottom corner
    UI_color.set(layer, win, "testing_banner")
    layer.set_font_size(15)
    layer.move_to(win.current["w"]-80, win.current["h"] - 7)
    layer.show_text(str(win.version))
    
    # Hude analytics button on the top
    def do():
        win.cur = "/set"
        win.url = "analytics"
        
    
    UI_elements.roundrect(layer, win,
        5,
        5, 
        win.current["w"]-(win.current["w"]/3)+45,
        40,
        10,
        do,
        "analytics",
        talk.text("analytics_tooltip"),
        url="story_editor")
    
    # Progressbar
    UI_color.set(layer, win, "progress_background")
    UI_elements.roundrect(layer, win,
        55,
        15, 
        win.current["w"]/3*2-10,
        20,
        10)
    
    timepassed  = 0.0
    projectdone = 0.0
    
    try:
        timepassed = win.analytics["timepassed"]
        projectdone = win.analytics["fraction"]
    except:
        pass
    
    # Timepassed
    UI_color.set(layer, win, "progress_time")
    UI_elements.roundrect(layer, win,
        55,
        15, 
        (win.current["w"]/3*2-10)*timepassed,
        20,
        10)
    
    # Project Done
    UI_color.set(layer, win, "progress_active")
    UI_elements.roundrect(layer, win,
        55,
        15, 
        (win.current["w"]/3*2-10)*projectdone,
        20,
        10)
    
    # Separator
    UI_color.set(layer, win, "node_background")
    layer.move_to(win.current["w"]/3*2+55, 5)
    layer.line_to(win.current["w"]/3*2+55, 45)
    layer.stroke()
    
    
    
    ############ CURRENT TASK SCHEDULED #############
    
    
    # FIRST WE NEED TO GET A LIST OF TASKS
    # This is going to be a simplified version of the same stuff as in the 
    # scheduling. But since we don't care what date we are in and trying to 
    # get the oldest unchecked task. Here we go.
    
    schedules = schedule.get_schedules(win.analytics["dates"])
    new_date_format = "%Y/%m/%d"
    today = datetime.datetime.strftime(datetime.datetime.today(), new_date_format)
    
    slist = []
    for date in schedules:
        for item in schedules[date]:
            if win.cur == item or not win.cur == "/set":
                slist.append([date, item, schedules[date][item]])
    
    
    # Now that we have our list we can start paring it the same way as in the
    # scheduling. Only removing some unnesesary stuff.
    foundtask = False
    taskname = ""
    taskurl  = ""
    taskcur  = ""
    
    for entry in slist:
        if not foundtask:
            for thing in entry[2]:
                if thing[0][3] == "[Checked]":
                    continue # We do not care about those who are checked here.
                elif thing[0][-1] != win.settings["Username"]:
                    continue # We do not care if it's not for us
                else:
                    foundtask = True
                    
                    # Here we are going to take out some data about this task
                    
                    # First if it's not for today let's get a color for it
                    if entry[0] != "1997/07/30":
                        draw = False
                        if entry[0] < today:
                            UI_color.set(layer, win, "node_badfile") # The Red
                            draw = True
                        elif entry[0] > today:
                            UI_color.set(layer, win, "node_asset") # The Purple
                            draw = True
                        if draw:
                            UI_elements.roundrect(layer, win,
                                win.current["w"]/3*2+60,
                                5, 
                                (win.current["w"]/3-65),
                                40,
                                10)
                    
                    name = entry[1][entry[1].rfind("/")+1:]
                    acur = entry[1].replace(name, "").replace("/", "")
                    
                    fullurl = ""
                    for e in thing[0][4][:-1]:
                        fullurl = fullurl+e+" > "
                    
                    
                    if acur in ["chr", "veh", "loc", "obj"]:
                        assetname = talk.text(acur)+": "+name
                    else:
                        assetname = entry[1]
                    
                    # ASSINGING TEXT VALUES
                    taskname = thing[0][4][-1]
                    taskurl  = fullurl
                    taskcur  = assetname.replace("/set","")
                    
                    # AND A TINY BUTTON TO ENTER WHAT EVER YOU ARE DOING
                    goto = "analytics"
                    if acur in ["chr", "veh", "loc","obj"]:
                        goto = "assets"
                        itemtype = "assets"
                    elif not acur:
                        itemtype = "files"
                    else:
                        goto = "script"
                        itemtype = "scenes"

                    def do():
                        win.url = goto
                        win.cur = entry[1]
                        win.current["asset_left_panel"] = "schedule"
                    UI_elements.roundrect(layer, win,
                        win.current["w"]/3*2+60,
                        5, 
                        (win.current["w"]/3-65),
                        40,
                        10,
                        button=do)
                    
                    break
        else:
            break
    
    # Schedule
    if taskname:
        UI_elements.image(layer, win, "settings/themes/"\
            +win.settings["Theme"]+"/icons/schedule.png", 
            win.current["w"]/3*2+60,
            5, 
            40,
            40)
    
    UI_color.set(layer, win, "text_normal")
    layer.set_font_size(20)
    layer.move_to(win.current["w"]/3*2+120, 25)
    layer.show_text(taskname)
    
    layer.set_font_size(12)
    layer.move_to(win.current["w"]/3*2+130+len(taskname)*12, 25)
    layer.show_text(taskurl)
    
    layer.set_font_size(12)
    layer.move_to(win.current["w"]/3*2+120, 40)
    layer.show_text(taskcur)
    
    
    ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
    fif = datetime.datetime.now()
    mil  = fif - stf
    perfStat.append([ "Analytics", mil.microseconds ])
    stf = datetime.datetime.now()
    ###################################################################
    
    
    
    
    ###### LEFT PANNEL #######
    
    
    # New Scene
    def do():
        
        # Okay let's make the adding the scene possible. 
        # First we need to know what scenes are there. So we don't overwrite
        # any existing scene.
        
        scenename = "Scene"
        count = 2
        while scenename in win.story["scenes"]:
            scenename = "Scene_"+str(count)
            count = count + 1
            
            
        # Now that we have an empty name. Let's add a scene.
        
        win.story["scenes"][scenename] = {
            "fraction":0.0,  # Percentage
            "position":[
                win.current["mx"]-win.story["camera"][0]-50,
                win.current["my"]-win.story["camera"][1]-30
                ],
            "size":[100, 60],
            "parent":"",     # For when it's in a Frame (Event)
            "shots":[[
                "text_block",[["text", '']]
                ]]
            }
        
        # Auto select the new scene
        
        win.story["selected"] = [["scene", scenename]]
        win.current["tool"] = "grab"
        
        # A hack I guess. I don't know what I'm doing. I'm trying to force
        # the motion on click.
        
        win.current["LMB"] = [win.current["mx"], win.current["my"], True]
        
        # In studio/studio_gtk.py there is a command that recognizes the length
        # of the LMB. And it's more then 2 it does some magic to make stuff move
        # without pressing the actuall key. It's slightly too clever even for me
        # so yeah.
                
        
    UI_elements.roundrect(layer, win,
        5,
        105, 
        40,
        40,
        10,
        do,
        "scene_new",
        talk.text("new_scene_tooltip")+"\n[N]",
        url="story_editor")
    
    # Shortcut
    if 110 in win.current["keys"] and not win.textactive:
        do()
        win.current["keys"] = []
    
    # Link Asset
    def do():
        def after(win, var):
            
            print (var)
            if var:
                win.story["links"].append([
                    "asset", var, [
                    win.current["mx"]-win.story["camera"][0]-75,
                    win.current["my"]-win.story["camera"][1]-75
                    ],
                    "" # Parent
                    ])
                
                # Now let's select and move the thing
                win.story["selected"] = [["asset", len(win.story["links"])-1]]
                win.current["tool"] = "grab"
                win.current["LMB"] = [win.current["mx"], win.current["my"], True]
            
                
        studio_dialogs.asset_select(win, "new_asset_story", after)
    
    UI_elements.roundrect(layer, win,
        5,
        155, 
        40,
        40,
        10,
        do,
        "obj_link",
        talk.text("link_asset_tooltip")+"\n[L]",
        url="story_editor")
    
    # Shortcut
    if 108 in win.current["keys"] and not win.textactive:
        do()
        win.current["keys"] = []
    
    
    # Link File
    def do():
        def after(win, var):
            if var:
                win.story["links"].append([
                    "file", var, [
                    win.current["mx"]-win.story["camera"][0]-75,
                    win.current["my"]-win.story["camera"][1]-75
                    ],
                    "" # Parent
                    ])
                
                # Now let's select and move the thing
                win.story["selected"] = [["file", len(win.story["links"])-1]]
                win.current["tool"] = "grab"
                win.current["LMB"] = [win.current["mx"], win.current["my"], True]
            
                
        studio_dialogs.file_select(win, "new_file_story", after, force=True)
    
    
    
    UI_elements.roundrect(layer, win,
        5,
        205, 
        40,
        40,
        10,
        do,
        "file_link",
        talk.text("link_file_tooltip")+"\n[I]",
        url="story_editor")
    
    # Shortcut
    if 105 in win.current["keys"] and not win.textactive:
        do()
        win.current["keys"] = []
    
    # Marker
    def do():
    
        
        markername = "Marker"
        count = 2
        while markername in win.story["markers"]:
            markername = "Marker_"+str(count)
            count = count + 1
        
        win.story["markers"][markername] = [
            win.current["mx"]-win.story["camera"][0]+50,
            win.current["my"]-win.story["camera"][1]-20,
            "" # Parent
            ]
        
        win.textactive = markername+"_marker"
        win.text[markername+"_marker"] = {
            "text"  :markername,  # Actuall text you are editing.
            "cursor":[len(str(markername)),len(str(markername))], # Cursor
            "insert":False, # Whether the insert mode is on
            "scroll":"markername_scroll" # If multiline. The pointer for the scroll value.
            }
        win.story["selected"] = [["marker", markername]]
        win.current["tool"] = "grab"
        win.current["LMB"] = [win.current["mx"], win.current["my"], True]
        
    UI_elements.roundrect(layer, win,
        5,
        255, 
        40,
        40,
        10,
        do,
        "pin",
        talk.text("marker_tooltip")+"\n[M]",
        url="story_editor")
    
    # Shortcut
    if 109 in win.current["keys"] and not win.textactive:
        do()
        win.current["keys"] = []
    
    
    if win.story["selected"]:
        # Event
        def do():
            eventname = "Event"
            count = 2
            while eventname in win.story["events"]:
                eventname = "Event_"+str(count)
                count = count + 1
            
            win.story["events"][eventname] = {
                "position":[0,0],
                "size":[0,0]
                }
                
            # Even going to delete it self if there will be noone who parenting
            # it.
            
            for thing in win.story["selected"]:
                if thing[0] == "scene":
                    win.story["scenes"][thing[1]]["parent"] = eventname    
                elif thing[0] in ["file", "asset"]:
                    win.story["links"][thing[1]][3] = eventname 
                elif thing[0] == "marker":
                    win.story["markers"][thing[1]][2] = eventname 
                
        UI_elements.roundrect(layer, win,
            5,
            305, 
            40,
            40,
            10,
            do,
            "event",
            talk.text("event_tooltip")+"\n[E]",
            url="story_editor")
            
        # Shortcut
        if 101 in win.current["keys"] and not win.textactive:
            do()
            win.current["keys"] = []
    
        
    # Renders
    def do():
        def after(win, var):
            pass
        
        studio_dialogs.render(win, "current_renders", after)
    
    UI_elements.roundrect(layer, win,
        5,
        405, 
        40,
        40,
        10,
        do,
        "render",
        talk.text("render_lists_tooltip"),
        url="story_editor")    
    
    # Let's draw on top of this button a little indicator of how many renders
    # are currently setup.
    
    if win.renders:
        count = str(len(win.renders))
        
        UI_color.set(layer, win, "node_background")
        UI_elements.roundrect(layer, win,
            30,
            405, 
            len(count)*12+6,
            25,
            5)
        layer.fill()
        UI_color.set(layer, win, "text_normal")
        layer.set_font_size(20)
        layer.move_to(33,425)
        layer.show_text(count)
    
    
    # Edit Video
    def do():
        def after(win, var):
            if var:
                print(var)
                oscalls.file_open(win, var)
        
        studio_dialogs.vse(win, "VSEs", after)
    
    UI_elements.roundrect(layer, win,
        5,
        455, 
        40,
        40,
        10,
        do,
        "vse",
        talk.text("vse_tooltip"),
        url="story_editor") 
    
    
    # Export to ODT
    def do():
        story.export_to_odt(win)
    
    UI_elements.roundrect(layer, win,
        5,
        555, 
        40,
        40,
        10,
        do,
        "export",
        talk.text("export_tooltip"),
        url="story_editor") 
    
    
    # Bottom
    
    # Multiuser
    def do():
        win.url = "multiuser"
    
    UI_elements.roundrect(layer, win,
        5,
        win.current["h"]-95, 
        40,
        40,
        10,
        do,
        "multiuser",
        talk.text("multiuser_tooltip"),
        url="story_editor")
    
    if win.multiuser["unread"]:
        count = str(win.multiuser["unread"])
        
        UI_color.set(layer, win, "node_background")
        UI_elements.roundrect(layer, win,
            30,
            win.current["h"]-100, 
            len(count)*12+6,
            25,
            5)
        layer.fill()
        UI_color.set(layer, win, "text_normal")
        layer.set_font_size(20)
        layer.move_to(33,win.current["h"]-83)
        layer.show_text(count)
    
    # Settings
    def do():
        win.url = "settings_layer"
    
    UI_elements.roundrect(layer, win,
        5,
        win.current["h"]-45, 
        40,
        40,
        10,
        do,
        "settings",
        talk.text("Settings"),
        url="story_editor")
    
    ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
    fif = datetime.datetime.now()
    mil  = fif - stf
    perfStat.append([ "Left Panel", mil.microseconds ])
    stf = datetime.datetime.now()
    ###################################################################
    
        
    ###### RIGHT PANNEL #######
    
    def select_character(win, var):
            
        if var:
            win.url = "assets"
            win.cur  = var
            win.current["tool"] = "selection"
    
    # Characters
    def do():
        
        studio_dialogs.asset_select(win, "new_asset_story", select_character, force=True, cur="chr")
    
    UI_elements.roundrect(layer, win,
        win.current["w"]-45,
        105, 
        40,
        40,
        10,
        do,
        "chr",
        talk.text("chr")+"\n[Shift-C]",
        url="story_editor")
    
    # Shortcut
    if 67 in win.current["keys"] and not win.textactive:
        do()
        win.current["keys"] = []
    
    # Vehicles
    def do():
        studio_dialogs.asset_select(win, "new_asset_story", select_character, force=True, cur="veh")
    
    UI_elements.roundrect(layer, win,
        win.current["w"]-45,
        155, 
        40,
        40,
        10,
        do,
        "veh",
        talk.text("veh")+"\n[Shift-V]",
        url="story_editor")
    
    # Shortcut
    if 86 in win.current["keys"] and not win.textactive:
        do()
        win.current["keys"] = []
    
    # Locations
    def do():
        studio_dialogs.asset_select(win, "new_asset_story", select_character, force=True, cur="loc")
    
    UI_elements.roundrect(layer, win,
        win.current["w"]-45,
        205, 
        40,
        40,
        10,
        do,
        "loc",
        talk.text("loc")+"\n[Shift-L]",
        url="story_editor")
    
    # Shortcut
    if 76 in win.current["keys"] and not win.textactive:
        do()
        win.current["keys"] = []
    
    # Other (obj)
    def do():
        studio_dialogs.asset_select(win, "new_asset_story", select_character, force=True, cur="obj")
    
    UI_elements.roundrect(layer, win,
        win.current["w"]-45,
        255, 
        40,
        40,
        10,
        do,
        "obj",
        talk.text("obj")+"\n[Shift-O]",
        url="story_editor")
    
    # Shortcut
    if 79 in win.current["keys"] and not win.textactive:
        do()
        win.current["keys"] = []
    
    # Sounds / Music
    def do():
        os.system("xdg-open "+win.project+"/mus")
    
    UI_elements.roundrect(layer, win,
        win.current["w"]-45,
        355, 
        40,
        40,
        10,
        do,
        "mus",
        talk.text("mus"),
        url="story_editor")
    
    # Help
    def do():
        def after(win, var):
           pass
        
        studio_dialogs.help(win, "help", after, SEARCH=talk.text("documentation_story_editor"))
    
    UI_elements.roundrect(layer, win,
        win.current["w"]-45,
        win.current["h"]-125, 
        40,
        40,
        10,
        do,
        "question",
        url="story_editor")
    
    # Folder
    def do():
        os.system("xdg-open "+win.project)
    
    UI_elements.roundrect(layer, win,
        win.current["w"]-45,
        win.current["h"]-75, 
        40,
        40,
        10,
        do,
        "folder",
        talk.text("project_folder"),
        url="story_editor")
    
    
    ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
    fif = datetime.datetime.now()
    mil  = fif - stf
    perfStat.append([ "Right Pannel", mil.microseconds ])
    stf = datetime.datetime.now()
    ###################################################################
    
    if win.url == "story_editor"\
    and int(win.current["mx"]) in range(50, int(win.current["w"]-50)) \
    and int(win.current["my"]) in range(50, int(win.current["h"]-30)):
        
        # The cross cursor
        win.current["cursor"] = win.cursors["cross"]
    
    
    ####### NODES #######
    
    # Clipping so it wont draw beyon the frame
    UI_elements.roundrect(layer, win,
        50,
        50, 
        win.current["w"] - 100,
        win.current["h"] - 80,
        30,
        fill=False)
    layer.clip()
    
    # Background Image
    if os.path.exists(win.project+"/set/banner.png"):
        UI_elements.image(layer, win, win.project+"/set/banner.png",
            50,
            50, 
            win.current["w"] - 100,
            win.current["h"] - 80,
            cell="background")
    elif os.path.exists(win.project+"/py_data/banner.png"):
        UI_elements.image(layer, win, win.project+"/py_data/banner.png",
            50,
            50, 
            win.current["w"] - 100,
            win.current["h"] - 80,
            cell="background")
    else:
        UI_elements.image(layer, win, "icon.png",
            50,
            50, 
            win.current["w"] - 100,
            win.current["h"] - 80,
            cell="background")
    
    UI_color.set(layer, win, "node_background")
    layer.rectangle(0,0,win.current["w"], win.current["h"])
    layer.fill()
    
    ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
    fif = datetime.datetime.now()
    mil  = fif - stf
    perfStat.append([ "Background Image", mil.microseconds ])
    stf = datetime.datetime.now()
    ###################################################################
    
    # You probably intersted where is the scroll function for this part. Well
    # see there is a thing. It's easier to write one from screach here. Because
    # you geassed it we are starting to draw story editor.
    
    # Let's prepare the camera first. 
    
    # Animation
    
    win.story["camera"][0] = UI_elements.animate("cameraX", win, 0, win.story["camera"][0])
    win.story["camera"][1] = UI_elements.animate("cameraY", win, 0, win.story["camera"][1])
    cx, cy = win.story["camera"]
    
    if win.url == "story_editor":
        if win.current["MMB"]:
            win.story["camera"][0] += ( win.current["mx"]-win.previous["mx"])
            win.story["camera"][1] += ( win.current["my"]-win.previous["my"])
            
            
        win.story["camera"][0] -= win.current["scroll"][0]*50
        win.story["camera"][1] -= win.current["scroll"][1]*50
        
    if cx != win.story["camera"][0] or cy != win.story["camera"][1]:
    
        UI_elements.animate("cameraX", win, win.story["camera"][0], force=True)
        UI_elements.animate("cameraY", win, win.story["camera"][1], force=True)
    
    ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
    fif = datetime.datetime.now()
    mil  = fif - stf
    perfStat.append([ "Camera position", mil.microseconds ])
    stf = datetime.datetime.now()
    ###################################################################
    
        
    # EVENTS (Frames)
    try:
        for event in win.story["events"]:
            
            # Loaction
            sx, sy = win.story["events"][event]["position"]
            
            
            # Scale
            ssx, ssy = win.story["events"][event]["size"]
            
            
            #Draw
            studio_nodes.event_node(layer, win, sx, sy, ssx, ssy, name=event)
            
            # Let's now check if the event even has anybody inside. It's a bit 
            # not the best way to implement it yet. Because I will need to look
            # through all items. But we can make it simpler if we find that it has
            # we can just break out of a thing.
            
            found = False
            
            for scene in win.story["scenes"]:
                if event == win.story["scenes"][scene]["parent"]:
                    found = True
                    break
                    
            if not found:         
                for link in win.story["links"]:
                    if event == link[3]:
                        found = True
                        break
            
            if not found:         
                for marker in win.story["markers"]:
                    if event == win.story["markers"][marker][2]:
                        found = True
                        break
                        
            
            # If nobody is inside. Delete the bastard.
            
            if not found:
                del win.story["events"][event]
    except:
        pass
    
    ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
    fif = datetime.datetime.now()
    mil  = fif - stf
    perfStat.append([ "Events", mil.microseconds ])
    stf = datetime.datetime.now()
    ###################################################################
    
    
    # SCENES
    try:
        for scene in win.story["scenes"]:
            
            # Loaction
            sx, sy = win.story["scenes"][scene]["position"]
            sx = sx + cx
            sy = sy + cy
            
            
            # Scale
            ssx, ssy = win.story["scenes"][scene]["size"]
            
            #Fraction
            sf = win.story["scenes"][scene]["fraction"]
            
            
            #Draw
            studio_nodes.scene_node(layer, win, sx, sy, ssx, ssy, name=scene, fraction=sf)
    except:
        pass        
    
    ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
    fif = datetime.datetime.now()
    mil  = fif - stf
    perfStat.append([ "Scenes", mil.microseconds ])
    stf = datetime.datetime.now()
    ###################################################################    
    
    # LINKS (Images, Stuff)
    
    for num, link in enumerate(win.story["links"]):
        
        linktype = link[0]
        linkname = link[1]
        lx = link[2][0] + cx
        ly = link[2][1] + cy
        
        # For the one inside the project. They should be always relative
        # so even if the project is in a complitely different location
        # on another machine. Where we have our Multiuser data. It should
        # be able to load these.
        
        if win.project in link[1]:
            link[1] = link[1].replace(win.project, "")
        
        
        studio_nodes.link_node(layer, win, lx, ly, name=linkname, num=num, linktype=linktype )
        
        
    
    ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
    fif = datetime.datetime.now()
    mil  = fif - stf
    perfStat.append([ "Files / Assets", mil.microseconds ])
    stf = datetime.datetime.now()
    ###################################################################
    
    # Let's put in the start and the end nodes. These are drawn on top of 
    # everything.
    
    studio_nodes.start_node(layer, win, 60,60,100,40)
    studio_nodes.end_node(layer, win, win.current["w"] - 160,
        win.current["h"] - 80,
        100,40)
    
    ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
    fif = datetime.datetime.now()
    mil  = fif - stf
    perfStat.append([ "Start / End Nodes", mil.microseconds ])
    stf = datetime.datetime.now()
    ###################################################################
    
    # MARKERS 
    try:
        for marker in win.story["markers"]:
            
            
            mx = win.story["markers"][marker][0] + cx
            my = win.story["markers"][marker][1] + cy
            
            studio_nodes.marker(layer, win, marker, mx, my)
    except:
        pass
    
    
    # MARKERS 
    try:
        for user in win.multiuser["users"]:
            if user != win.multiuser["userid"]:
                
                mx = 0-win.multiuser["users"][user]["camera"][0] +cx + win.current["w"]/2
                my = 0-win.multiuser["users"][user]["camera"][1] +cy + win.current["h"]/2
                
                studio_nodes.user(layer, win, win.multiuser["users"][user]["username"], mx, my, user)
    except Exception as e:
        print(e, "USER RENDERING")
    
    ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
    fif = datetime.datetime.now()
    mil  = fif - stf
    perfStat.append([ "Markers", mil.microseconds ])
    stf = datetime.datetime.now()
    ###################################################################
    
    # In case there is a selection bug
    if not win.story["selected"] and win.current["tool"] != "connect":
        win.current["tool"] = "selection"
    
    # Selector visualization
    if win.current["LMB"] and win.current["tool"] == "selection" and win.url == "story_editor":
        
        # Draw selection box
        UI_color.set(layer, win, "progress_background")
        layer.rectangle(
            win.current["mx"],
            win.current["my"],
            win.current["LMB"][0] - win.current["mx"],
            win.current["LMB"][1] - win.current["my"]
            )
        layer.stroke()
    
    # Now let's draw the cool AF multi selection zone thingy
    
    # Draw selection box
    if len(win.story["selected"]) > 1 and win.current["tool"] == "selection":
        UI_color.set(layer, win, "progress_background")
        layer.rectangle(
            win.szone[0][0]-10,
            win.szone[0][1]-10,
            win.szone[1][0]+20,
            win.szone[1][1]+20
            )
        layer.stroke()
    
    # Now I want to make a tiny widget that will resize the stuff.
    
    if win.story["selected"]:
        
        if win.current["tool"] == "selection":
            
            draw_circle = True
            if len(win.story["selected"]) == 1:
                if win.story["selected"][0][0] != "scene":
                    draw_circle = False
            
            if draw_circle:        
                UI_color.set(layer, win, "node_badfile")
                UI_elements.roundrect(layer, win,
                    win.szone[0][0]+win.szone[1][0],
                    win.szone[0][1]+win.szone[1][1], 
                    0,
                    0,
                    10)
                UI_color.set(layer, win, "progress_background")
                UI_elements.roundrect(layer, win,
                    win.szone[0][0]+win.szone[1][0],
                    win.szone[0][1]+win.szone[1][1], 
                    0,
                    0,
                    10,
                    fill=False)
                layer.stroke()
        
        elif win.current["tool"] == "scale":
            UI_color.set(layer, win, "node_badfile")
            UI_elements.roundrect(layer, win,
                win.current["mx"]-10,
                win.current["my"]-10, 
                0,
                0,
                10)
            UI_color.set(layer, win, "progress_background")
            UI_elements.roundrect(layer, win,
                win.current["mx"]-10,
                win.current["my"]-10, 
                0,
                0,
                10,
                fill=False)
            layer.stroke()
        
        if int(win.current["mx"]) in range(int(win.szone[0][0]+win.szone[1][0]), int(win.szone[0][0]+win.szone[1][0]+20))\
        and int(win.current["my"]) in range(int(win.szone[0][1]+win.szone[1][1]), int(win.szone[0][1]+win.szone[1][1]+20))\
        and win.current["tool"] == "selection":
            
            UI_color.set(layer, win, "text_normal")
            UI_elements.roundrect(layer, win,
                win.szone[0][0]+win.szone[1][0],
                win.szone[0][1]+win.szone[1][1], 
                0,
                0,
                10,
                fill=False)
            layer.stroke()
            
            win.current["cursor"] = win.cursors["arrow"]
            
            if win.current["LMB"] and not win.previous["LMB"]:
                
                win.current["tool"] = "scale"
    
    if win.current["tool"] == "scale" and not win.current["LMB"]:
        win.current["tool"] = "selection"
    

    
    # Canceling seletion. I move it here so it would not interfire with the
    # the rest of the program.
    if win.current["LMB"] and win.current["tool"] == "selection" and win.url == "story_editor":
        
        # Undo selection
        if int(win.current["LMB"][0] - win.current["mx"]) in range(-10, 10)\
        and int(win.current["LMB"][1] - win.current["my"])in range(-10, 10)\
        and int(win.current["mx"]) in range(50, int(win.current["w"]-50)) \
        and int(win.current["my"]) in range(50, int(win.current["h"]-30))\
        and 65505 not in win.current["keys"]:
            win.story["selected"] = []       
            win.textactive = ""     
            
    
    
    # Let's draw the line while connecting 2 scenes together.
    
    if win.current["tool"] == "connect":
        
        win.current["cursor"] = win.cursors["arrow"]
        
        if not win.current["LMB"]:
            win.current["tool"] = "selection"
        
        fr = win.current["draw_dot"]
        if type(fr) == list:
            fr = fr[0]+":"+fr[1]
        
        try:
            UI_color.set(layer, win, "node_script")
            layer.move_to(
                win.out_dots[fr][0], 
                win.out_dots[fr][1]
                )
            layer.line_to(win.current["mx"], win.current["my"])
            layer.stroke()
        except:
            pass
    
    ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
    fif = datetime.datetime.now()
    mil  = fif - stf
    perfStat.append([ "Selection", mil.microseconds ])
    stf = datetime.datetime.now()
    ###################################################################
    
    # The undo history is quite a new adition so the limit setting might
    # not exists. So let's make it if so.
    if "Undo_Limit" not in win.settings:
        win.settings["Undo_Limit"] = 32
        settings.write("Undo_Limit", 32)
    
    if win.animations["cameraX"][1] == cx:
        win.current["camera_arrived"] = True
    else:
        win.current["camera_arrived"] = False
    
    
        
    
    # Save story. I'm going to do it the same way as in the old Blender-Organizer
    if win.url == "story_editor":
        savenow = False
        if win.previous["LMB"] and not win.current["LMB"]:
            savenow = True
        elif win.previous["RMB"] and not win.current["RMB"]:
            savenow = True
        elif win.previous["MMB"] and not win.current["MMB"]:
            savenow = True
        elif win.previous["keys"] and not win.current["keys"]:
            savenow = True
        elif win.current["camera_arrived"] and not win.previous["camera_arrived"]:
            savenow = True
        
        if savenow:
            
            win.current["cursor"] = win.cursors["watch"]
                    
            # Now let's run the history record.
            story.undo_record(win)
            
            story.save(win.project, win.story)
            analytics.save(win.project, win.analytics)
            
            # Need to reload the story to reload the fractions of the scenes.
            win.story = story.load(win.project)
            
            # Multiuser sycning
            win.multiuser["request"] = "story"
            
    ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
    fif = datetime.datetime.now()
    mil  = fif - stf
    perfStat.append([ "File Saving", mil.microseconds ])
    stf = datetime.datetime.now()
    ###################################################################
    
    # To selected
    if 65454 in win.current["keys"]  and win.story["selected"] and not win.textactive:
        
        nex = cx-win.szone[0][0] - win.szone[1][0]/2 + win.current["w"]/2
        ney = cy-win.szone[0][1] - win.szone[1][1]/2 + win.current["h"]/2
        
        UI_elements.animate("cameraX", win, win.story["camera"][0],nex, force=True)
        UI_elements.animate("cameraY", win, win.story["camera"][1],ney, force=True)
        
    # Undo
    if 65507 in win.current["keys"] and 122 in win.current["keys"] and not win.textactive:
        story.undo(win)
        win.current["keys"] = []
        
    # Redo
    if 65507 in win.current["keys"] and 121 in win.current["keys"] and not win.textactive:
        story.redo(win)
        win.current["keys"] = []
        
    # Grab
    if 103 in win.current["keys"]  and win.story["selected"] and not win.textactive:
        win.current["tool"] = "grab"
        win.current["LMB"] = [win.current["mx"], win.current["my"], True]
    
    # Scale
    if 115 in win.current["keys"]  and win.story["selected"] and not win.textactive:
        win.current["tool"] = "scale"
        win.current["LMB"] = [win.current["mx"], win.current["my"], True]
    
    # Deletion
    if 65535 in win.current["keys"] and win.current["tool"] == "selection"\
    and win.url == "story_editor" and win.story["selected"] and not win.textactive:
        
        win.url = "story_deletion_dialog"
    
    ########### TIMES RECORDING FOR PERFONMANCE MEASURING #############
    fif = datetime.datetime.now()
    mil  = fif - stf
    perfStat.append([ "Short Cuts", mil.microseconds ])
    stf = datetime.datetime.now()
    ###################################################################
    
    ############### PERFORMCE TESTING GROUND ##############
    
    if win.current["testing"]: 
                
        
        h = win.current["h"]+200
        w = win.current["w"]
        
        UI_color.set(layer, win, "darker_parts")
        UI_elements.roundrect(layer, win,100, h-(len(perfStat)*15)-30-300, 500,len(perfStat)*15+30, 10)
        
        
        l = 0
        s = 0
        for i in perfStat:
            if int(i[1]) > l:
                l = int(i[1])
            s = s + int(i[1])
        for n, i in enumerate(perfStat):
            
            #UI_color.set(layer, win, "progress_background")
            #UI_elements.roundrect(layer, win, 110 + 270, h-(len(perfStat)*15)-20+10+15*n-300, 200,10, 5)
            
            
            layer.set_source_rgb(1,1,1)
            if int(i[1]) == l:
                layer.set_source_rgb(1,0,0)
            elif int(i[1]) < 1000:
                layer.set_source_rgb(0,1,0)
            layer.set_font_size(10)
            layer.move_to( 110, h-(len(perfStat)*15)+15*n-300)
            
            p = float(i[1]) / s *100
            
            layer.show_text(str(i[0])+" - "+str(i[1])+" MCRS "+str(int(round(p)))+"%")
            
            
            #UI_color.set(layer, win, "progress_active")
            UI_elements.roundrect(layer, win, 110 + 270, h-(len(perfStat)*15)-20+10+15*n-300, int(round(p))*2,10, 5)
    
    
        
    return surface