#####################################################################
#                                                                   #
#  THIS IS A SOURCE CODE FILE FROM A PROGRAM TO INTERACT WITH THE   #
# LBRY PROTOCOL ( lbry.com ). IT WILL USE THE LBRY SDK ( lbrynet )  #
# FROM THEIR REPOSITORY ( https://github.com/lbryio/lbry-sdk )      #
# WHICH I GONNA PRESENT TO YOU AS A BINARY. SINCE I DID NOT DEVELOP #
# IT AND I'M LAZY TO INTEGRATE IN A MORE SMART WAY. THE SOURCE CODE #
# OF THE SDK IS AVAILABLE IN THE REPOSITORY MENTIONED ABOVE.        #
#                                                                   #
#      ALL THE CODE IN THIS REPOSITORY INCLUDING THIS FILE IS       #
# (C) J.Y.Amihud and Other Contributors 2021. EXCEPT THE LBRY SDK.  #
# YOU CAN USE THIS FILE AND ANY OTHER FILE IN THIS REPOSITORY UNDER #
# THE TERMS OF GNU GENERAL PUBLIC LICENSE VERSION 3 OR ANY LATER    #
# VERSION. TO FIND THE FULL TEXT OF THE LICENSE GO TO THE GNU.ORG   #
# WEBSITE AT ( https://www.gnu.org/licenses/gpl-3.0.html ).         #
#                                                                   #
# THE LBRY SDK IS UNFORTUNATELY UNDER THE MIT LICENSE. IF YOU ARE   #
# NOT INTENDING TO USE MY CODE AND JUST THE SDK. YOU CAN FIND IT ON #
# THEIR OFFICIAL REPOSITORY ABOVE. THEIR LICENSE CHOICE DOES NOT    #
# SPREAD ONTO THIS PROJECT. DON'T GET A FALSE ASSUMPTION THAT SINCE #
# THEY USE A PUSH-OVER LICENSE, I GONNA DO THE SAME. I'M NOT.       #
#                                                                   #
# THE LICENSE CHOSEN FOR THIS PROJECT WILL PROTECT THE 4 ESSENTIAL  #
# FREEDOMS OF THE USER FURTHER, BY NOT ALLOWING ANY WHO TO CHANGE   #
# THE LICENSE AT WILL. SO NO PROPRIETARY SOFTWARE DEVELOPER COULD   #
# TAKE THIS CODE AND MAKE THEIR USER-SUBJUGATING SOFTWARE FROM IT.  #
#                                                                   #
#####################################################################

import time
import json
import threading
import urllib.request
from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import GLib
from gi.repository import Pango
from gi.repository import GdkPixbuf

from flbry import markdown
from flbry import ui
from flbry import fetch
from flbry import settings

# TODO: Get rid of this string and use win.settings["comment_api"] instead



# This is going into the end of comments to promote FastLBRY GTK
BUTTON_GTK_PROMOTE = "\n\n[![](https://player.odycdn.com/api/v4/streams/free/button_GTK/d025c8ec2cdb5122a85b374b7bc453ba11d9409d/6526ef)](https://notabug.org/jyamihud/FastLBRY-GTK)"
BUTTON_GTK_PROMOTE_TEXT = "\n\n[Sent via FastLBRY GTK](https://notabug.org/jyamihud/FastLBRY-GTK)"

def list_comments( win, data, page=1, megabox=False):

    claim_id = data["claim_id"]
    
    # gets list of comment
    
    params = {
            "claim_id": claim_id,
            "page": page,
#           "page_size": page_size,
            "sort_by": 0,
            "top_level": False,
        }

    time.sleep(1) # too fast
    
    out = comment_request(win, "comment.List", params)
    out = get_reactions(win, out)

    return [win, out, data,  megabox]

def render_single_comment(win, box, i):

    claim_id = i["claim_id"]

    items = win.commenting[claim_id]["data"]["result"]["items"]

    def send_reaction(w, reaction):

        remove = not w.get_active()
        print("remove", remove)

        sigs = sign(win.channel["name"], win.channel["name"])
        
        params = {
                "channel_name": win.channel["name"],
                "channel_id": win.channel["claim_id"],
                "comment_ids": i.get("comment_id"),
                "type": reaction,
                **sigs
            }
        if remove:
            params["remove"] = True


        out = comment_request(win, "reaction.React", params)
        print(out)
    
    # Like / Dislike ratio

    reactionbox = Gtk.HBox()

    like_dislike_ratio_box = Gtk.VBox()

    like_dislike_box = Gtk.HBox()
    print(i)
    likes = i.get("reactions", {}).get("like", 0)+i.get("my_reactions", {}).get("like", 0)

    like = Gtk.ToggleButton("  👍 "+str(likes)+"  ")
    like.set_active(i.get("my_reactions", {}).get("like", 0))
    like.connect("clicked", send_reaction, "like")
    like.set_relief(Gtk.ReliefStyle.NONE)
    like_dislike_box.pack_start(like, False, False, 0)

    dislikes = i.get("reactions", {}).get("dislike", 0)+i.get("my_reactions", {}).get("dislike", 0)

    dislike = Gtk.ToggleButton("  👎 "+str(dislikes)+"  ")
    dislike.set_active(i.get("my_reactions", {}).get("dislike", 0))
    dislike.set_relief(Gtk.ReliefStyle.NONE)
    dislike.connect("clicked", send_reaction, "dislike")
    like_dislike_box.pack_start(dislike, False, False, 0)


       

    
    like_dislike_ratio_box.pack_start(like_dislike_box, False, False, False)


    
    try:
        frac = likes / (likes + dislikes)
    except:
        frac = 0
    ratio_bar = Gtk.ProgressBar()
    ratio_bar.set_fraction(frac)
    like_dislike_ratio_box.pack_start(ratio_bar, True, True,0)

    reactionbox.pack_start(like_dislike_ratio_box, False, False, False)

    #creator_like

    creator_likes = i.get("reactions", {}).get("creator_like", 0)+i.get("my_reactions", {}).get("creator_like", 0)

    creator_like = Gtk.ToggleButton("  ❤ "+str(creator_likes)+"  ")
    creator_like.set_relief(Gtk.ReliefStyle.NONE)
    creator_like.set_active(i.get("my_reactions", {}).get("creator_like", 0))
    creator_like.connect("clicked", send_reaction, "creator_like")
    reactionbox.pack_start(creator_like, False, False, 0)
    
    bones = i.get("reactions", {}).get("bones", 0)+i.get("my_reactions", {}).get("bones", 0)

    bone = Gtk.ToggleButton("  🍖 "+str(bones)+"  ")
    bone.set_relief(Gtk.ReliefStyle.NONE)
    bone.set_active(i.get("my_reactions", {}).get("bones", 0))
    bone.connect("clicked", send_reaction, "bones")
    reactionbox.pack_start(bone, False, False, 0)

    frozen_toms = i.get("reactions", {}).get("frozen_tom", 0)+i.get("my_reactions", {}).get("frozen_tom", 0)

    frozen_tom = Gtk.ToggleButton("  🍦 "+str(frozen_toms)+"  ")
    frozen_tom.set_relief(Gtk.ReliefStyle.NONE)
    frozen_tom.set_active(i.get("my_reactions", {}).get("frozen_tom", 0))
    frozen_tom.connect("clicked", send_reaction, "frozen_tom")
    reactionbox.pack_start(frozen_tom, False, False, 0)

    mind_blowns = i.get("reactions", {}).get("mind_blown", 0)+i.get("my_reactions", {}).get("mind_blown", 0)

    mind_blown = Gtk.ToggleButton("  🤯 "+str(mind_blowns)+"  ")
    mind_blown.set_relief(Gtk.ReliefStyle.NONE)
    mind_blown.connect("clicked", send_reaction, "mind_blown")
    mind_blown.set_active(i.get("my_reactions", {}).get("mind_blown", 0))
    reactionbox.pack_start(mind_blown, False, False, 0)

    
    ########### REPLY ############

    def reply_set(w):
        for ch in win.commenting[claim_id]["reply"]["box"].get_children():
            ch.destroy()
        win.commenting[claim_id]["reply"]["to"] = i["comment_id"]

        reply_frame = Gtk.Frame(label="  Replying to:  ")
        reply_frame.set_shadow_type(Gtk.ShadowType.ETCHED_OUT)
        reply_box = Gtk.HBox()
        reply_frame.add(reply_box)

        chbox = Gtk.HBox()
        channel_button = ui.load(win, resolve_channel, render_channel, win, i["channel_url"])
        chbox.pack_start(channel_button, False, False, 0)
        reply_box.pack_start(chbox, False, False, 4)
        comment_label = Gtk.Label(i["comment"].split("\n")[0][:100]+" ...")
        comment_label.set_line_wrap_mode( Gtk.WrapMode.WORD )
        comment_label.set_line_wrap(True)
        reply_box.pack_start(comment_label,  False, False, 10)

        
        win.commenting[claim_id]["reply"]["box"].pack_start(reply_frame, True, True, 5)

        ##### DELETE REPLY ####
        def delete_set(w):
            for ch in win.commenting[claim_id]["reply"]["box"].get_children():
                ch.destroy()
            win.commenting[claim_id]["reply"]["to"] = ""
        
        delete = Gtk.Button()
        delete.connect("clicked", delete_set)
        delete.set_relief(Gtk.ReliefStyle.NONE)
        delete.add(ui.icon(win, "edit-delete"))
        win.commenting[claim_id]["reply"]["box"].pack_end(delete, False, False, 0)
        
        
        win.commenting[claim_id]["reply"]["box"].show_all()
    reply = Gtk.Button("  Reply  ")
    reply.set_relief(Gtk.ReliefStyle.NONE)
    reply.connect("clicked", reply_set)
    reactionbox.pack_end(reply, False, False, False)

    box.pack_end(reactionbox, False, False, 0)

    
    comment_text = i["comment"]
    supporter = False
    if BUTTON_GTK_PROMOTE in comment_text or BUTTON_GTK_PROMOTE_TEXT in comment_text:
        supporter = True
        comment_text = comment_text.replace(BUTTON_GTK_PROMOTE, "").replace(BUTTON_GTK_PROMOTE_TEXT, "")
        

    def force_size(w, e):
        
        if w.get_allocated_width() > w.get_parent().get_parent().get_parent().get_parent().get_parent().get_allocated_width() - 10:
    
            all1 = w.get_parent().get_parent().get_parent().get_parent().get_parent().get_allocation()
            all2 = w.get_allocation()
            all1.y = all2.y
            
            w.size_allocate(all1)

    commentbox = Gtk.Frame()
    commentbox.set_border_width(5)
    comment_field = Gtk.TextView()
    if win.settings["comments_auto_resize"]:
        comment_field.connect("draw", force_size)
    comment_field.set_wrap_mode(Gtk.WrapMode.WORD_CHAR )
    comment_field.set_editable(False)
    comment_field.set_hexpand(False)
    comment_buffer = comment_field.get_buffer()
    comment_buffer.set_text(comment_text)
    markdown.convert(win, comment_field, imwidth=200)
    commentbox.add(comment_field)
    box.pack_end(commentbox,  True, True, 0)

        
    # comment_label = Gtk.Label(comment_text)
    # comment_label.set_selectable(True)
    # comment_label.set_line_wrap_mode( Gtk.WrapMode.WORD )
    # comment_label.set_line_wrap(True)
    # comment_label.set_max_width_chars(20)
    # box.pack_end(comment_label,  True, True, 10)

    def resolve_channel(win, url):
        out = fetch.lbrynet("resolve", {"urls":url})
        out = out[url]
        return [win, out]
    def render_channel(out):
        win, out = out
        return ui.go_to_channel(win, out)

    # Sometimes it's a reply

    if "parent_id" in i:
        for b in items:
            if b["comment_id"] == i["parent_id"]:
                expand = Gtk.Expander(label="  In Reply to:  ")
                reply_frame = Gtk.Frame()
                reply_frame.set_border_width(10)
                expand.add(reply_frame)
                reply_frame.set_shadow_type(Gtk.ShadowType.ETCHED_OUT)
                reply_box = Gtk.VBox()
                reply_frame.add(reply_box)

                render_single_comment(win, reply_box, b)
                
                box.pack_end(expand,  True, True, 10)
                break


    # each channel will need to be resolved on fly
    if "channel_url" in i:
        chbox = Gtk.HBox()
        channel_button = ui.load(win, resolve_channel, render_channel, win, i["channel_url"])
        chbox.pack_start(channel_button, False, False, 0)

        if "support_amount" in i and i["support_amount"]:
            chbox.pack_start(ui.icon(win, "emblem-favorite"), False, False, 0)
            chbox.pack_start(Gtk.Label("  "+str(i["support_amount"])+" LBC"), False, False, 0)

        if supporter:
            chbox.pack_start(ui.icon(win, "emblem-favorite"), False, False, 0)
            chbox.pack_start(Gtk.Label("  Promoter of FastLBRY  "), False, False, 0)

            
            
        box.pack_end(chbox, False, False, 4)


    box.pack_end(Gtk.HSeparator(), False, False, 0)

def render_comments(out, megabox=False):
    
    win, out, data,  megabox = out

    if not megabox:
        megabox = Gtk.VBox()
        megabox.show_all()

    # renders a list of comments

 
    box = Gtk.VBox()
    box.set_hexpand(False)

    # I want to setup a little daemon to update the comments
    # automatically

    claim_id = data["claim_id"]
    try:
        the_title = data["value"]["title"]
    except:
        the_title = data["name"]
    
    if out["result"]["page"] == 1: # If it's the first page

        
        win.commenting[claim_id]["box"] = box
        win.commenting[claim_id]["data"] = out

        win.check_comment_daemon_keep_alive = True
        load_thread = threading.Thread(target=comment_daemon, args=[win, data, the_title])
        load_thread.setDaemon(True)
        load_thread.start()
        def kill_daemon(w):
            win.check_comment_daemon_keep_alive = False
        box.connect("destroy", kill_daemon)

        
    try:
        items = out["result"]["items"]
        for i in items:
            if i not in win.commenting[claim_id]["data"]["result"]["items"]:
                win.commenting[claim_id]["data"]["result"]["items"].append(i)
    except:
        items = []
    for i in reversed(items):
        
        #print("\n\n:::::::::::::::::\n\n", i)
        render_single_comment(win, box, i)
        
    box.show_all()

    # The top level box containing about 50 comments
    megabox.pack_start(box, False, False, 0)
    lastthing(win, out, data, megabox)
    megabox.show_all()

    
    return megabox

def comment_daemon(win, data, the_title=""):

    # This function will be a daemon for the current comment system to
    # load all new comments that happen while the user it on the page.

    claim_id = data["claim_id"]
    
    while win.commenting[claim_id]["keep_alive"]:


        
        time.sleep(2) # Update every two seconds ( I don't want it to crash )

        n = win.commenting[claim_id]["data"]

        try:
            claim_id = n["result"]["items"][0]["claim_id"]
        except:
            n["result"]["items"] = []
            continue

        win, out, data, megabox = list_comments(win, data)

        ##### LOGIC OF ADDING MISSING COMMENTS INTO THE BOX ####

        for i in reversed(out["result"]["items"]):
            if i not in  n["result"]["items"]:
                ids = []
                for b in n["result"]["items"]:
                    ids.append(b["comment_id"])

                ######## FOUND A NEW COMMENT #######
                
                if i["comment_id"] not in ids:

                    try:
                        channel = i["channel_name"]
                    except:
                        channel = "[anonymous]"
                    text = i["comment"]
                    print("COMMENT FROM ", channel, "IS", text)
                    force = win.resolved["claim_id"] != claim_id
                    ui.notify(win, channel+" Commented on "+the_title, text, force=force)

                    win.commenting[claim_id]["data"]["result"]["items"].append(i)
                    print(i["comment_id"])
                    box = win.commenting[claim_id]["box"]
                    def render(win, box, i):
                        render_single_comment(win, box, i)
                        box.show_all()
                    GLib.idle_add(render, win, box, i)

        def br(w):
            if not win.commenting[claim_id]["listen"]:
                win.commenting[claim_id]["keep_alive"] = False
        win.commenting[claim_id]["box"].connect("destroy", br)


def lastthing(win, out, data, megabox):

    # This will hack itself to load more comments when you reached the end.
    
    spinner_more = ui.icon(win, "loading", "gif")
    
    megabox.pack_start(spinner_more, False, False, 0)
    

    def draw_event(w, e):
        print("EVENT")
        w.destroy()
        
        try:
            claim_id = out["result"]["items"][0]["claim_id"]
            page = out["result"]["page"] + 1
            ui.load(win, list_comments, render_comments, win, data, page, megabox, wait=False )
            
        except Exception as e:
            print("ERROR IS:", e)
            
    
    spinner_more.connect("draw", draw_event)
    
    
def get_reactions(win, out):

    # Adds reactions list to the out

    try:
        claim_id = out["result"]["items"][0]["claim_id"]
        ids = ""
        for i in out["result"]["items"]:
            ids = ids + i["comment_id"] + ","
        ids = ids[:-1]
    except:
        return out
    sigs = sign(win.channel["name"], win.channel["name"])
    rec =  {
        "channel_name":win.channel["name"],
        "channel_id":win.channel["claim_id"],
        "claim_id":claim_id,
        "comment_ids":ids,
        **sigs
    }
    rec = comment_request(win, "reaction.List", rec, addition="?m=reaction.List")

    for i in out["result"]["items"]:
        try:
            i["reactions"] = rec["result"]["others_reactions"][i["comment_id"]]
        except:
            pass
        try:
            i["my_reactions"] = rec["result"]["my_reactions"][i["comment_id"]]
        except:
            pass
    
    
    return out
    
def comment_request(win, method: str, params: dict, addition=""):
    """
    Sends a request to the comment API
    """
    data = {
        "method": method,
        "id": 1,
        "jsonrpc":"2.0",
        "params": params
    }
    data = json.dumps(data).encode()

    headers = {
        "Content-Type": "application/json"
    }

    
    
    try:
        req = urllib.request.Request(win.settings["comment_api"], data, headers)
        res = urllib.request.urlopen(req)
        out = res.read().decode()
        return json.loads(out)
    except Exception as e:
        print("COMMENT ERROR:", e)
        return

def comment_input(win, claim_id):


    # claim_id = win.resolved["claim_id"]
    
    # This is the input for new comments.

    vbox = Gtk.VBox()
    pannel = Gtk.HBox()
    vbox.pack_start(pannel, False, False, False)

    ################## LISTEN BUTTON ###############

    try:
        give_listen = win.commenting[claim_id]["listen"]
    except:
        give_listen = False
        
    win.commenting[claim_id] = {"box": False,
                                "data":{},
                                "listen":give_listen,
                                "keep_alive":True}
    
    if win.settings["notifications"]:
       
        lbox = Gtk.HBox()
        lbox.pack_start(Gtk.Label("  Listen  "), False, False, False)
        listen = Gtk.Switch()
        
        def lclick(w, u):
            win.commenting[claim_id]["listen"] = listen.get_active()
        try:
            listen.set_active(win.commenting[claim_id]["listen"])
        except Exception as e:
            print("Switch is:", e)
        listen.connect("notify::active", lclick)
        lbox.pack_start(listen, False, False, False)
        pannel.pack_start(lbox, False, False, False)

    
    if win.channel:

        ############# BOX FOR REPLIES ##############

        # There will be a hidden box for replies. And when
        # the user presses the 'reply' button on any
        # of the current comments, it will fill up the box.

        win.commenting[claim_id]["reply"] = {"box":Gtk.HBox(),
                                   "to":""}
        vbox.pack_start( win.commenting[claim_id]["reply"]["box"], False, False, False)


        ############### SEND BUTTON ###################
        
        def send_do(w):

            tb = view.get_buffer()
            message = tb.get_text(tb.get_start_iter(), tb.get_end_iter(), True)
            #tb.set_text("")
            send_comment(win, message, claim_id, tb, support=support_bid_entry)
        
        send = Gtk.Button()
        send.connect("clicked", send_do)
        send.set_relief(Gtk.ReliefStyle.NONE)
        sendbox = Gtk.HBox()
        sendbox.pack_start(ui.icon(win, "document-send"), False, False, 0)
        sendbox.pack_start(Gtk.Label("  Send  "), False, False, 0)
        pannel.pack_end(send, False, False, False)
        send.add(sendbox)


        


        ############## TEXT INPUT ##############

        inputbox = Gtk.HPaned()
        inputbox.set_position(500)
        vbox.pack_start(inputbox, True, True, True)
        
        frame = Gtk.Frame()
        scrl = Gtk.ScrolledWindow()
        view = Gtk.TextView()
        view.override_font(Pango.FontDescription("Monospace"))
        view.set_wrap_mode(Gtk.WrapMode.WORD)
        #scrl.set_size_request(100,100)
        scrl.add(view)
        #view.set_size_request(100,100)
        frame.add(scrl)
        inputbox.add1(frame)

        ############## MARKDOWN PREVIEW ##############

        commentbox = Gtk.Frame()
        scrl2 = Gtk.ScrolledWindow()
        comment_field = Gtk.TextView()
        comment_field.set_wrap_mode(Gtk.WrapMode.WORD )
        comment_field.set_editable(False)
        comment_field.set_hexpand(False)
        comment_buffer = comment_field.get_buffer()
        scrl2.add(comment_field)
        commentbox.add(scrl2)
        inputbox.add2(commentbox)

        def on_changed(w):

            tb = view.get_buffer()
            message = tb.get_text(tb.get_start_iter(), tb.get_end_iter(), True)
            comment_buffer.set_text(message)
            markdown.convert(win, comment_field, 200)
            comment_field.show_all()

            # Scrolling to the end
            # TODO: Make it scroll to the character
            adj = scrl2.get_vadjustment()
            adj.set_value(  adj.get_upper() )
            
        view.get_buffer().connect("changed", on_changed)

        ################# MARKDOWN CONTROLLS #################

        pannel.pack_start(Gtk.VSeparator(), False, False, 10)

        def do_mark(w, r, l):

            tb = view.get_buffer()
            s, e = tb.get_selection_bounds()
            tb.insert(s, r)
            s, e = tb.get_selection_bounds()
            tb.insert(e, l)
            
            print(r, l)
            
        bold = Gtk.Button()
        bold.connect("clicked", do_mark, "**", "**")
        bold.add(ui.icon(win, "format-text-bold"))
        bold.set_relief(Gtk.ReliefStyle.NONE)
        pannel.pack_start(bold, False, False, False)

        italic = Gtk.Button()
        italic.connect("clicked", do_mark, "*", "*")
        italic.add(ui.icon(win, "format-text-italic"))
        italic.set_relief(Gtk.ReliefStyle.NONE)
        pannel.pack_start(italic, False, False, False)

        code = Gtk.Button("</>")
        code.connect("clicked", do_mark, "`", "`")
        code.set_relief(Gtk.ReliefStyle.NONE)
        pannel.pack_start(code, False, False, False)

        pannel.pack_start(Gtk.VSeparator(), False, False, 10)

        #################### PROMOTE BUTTON ######################

        pannel.pack_start(ui.icon(win, "emblem-favorite"), False, False, 0)
        pannel.pack_start(Gtk.Label("  Promote FastLBRY:  "), False, False, 0)
        switch = Gtk.Switch()
        switch.set_tooltip_text("Adds a little link to FastLBRY visible in all other LBRY apps.")
        pannel.pack_start(switch, False, False, 0)
        switch.set_active(win.settings["promote_fast_lbry_in_comments"])
        
        def on_promote(w, e):
            win.settings["promote_fast_lbry_in_comments"] = switch.get_active()
            settings.save(win.settings)
            
        switch.connect("notify::active", on_promote)    

        
        pannel.pack_start(Gtk.VSeparator(), False, False, 10)

        ################# SUPPORT AMOUNT ##########################

        pannel.pack_start(ui.icon(win, "emblem-favorite"), False, False, 0)
        pannel.pack_start(Gtk.Label("  Support Amount:  "), False, False, 0)

        support_bid_adjust = Gtk.Adjustment(0,
                            lower=0,
                            upper=1000000000,
                            step_increment=0.1) 
        support_bid_entry  = Gtk.SpinButton(adjustment=support_bid_adjust,
                                digits=4)
        pannel.pack_start(support_bid_entry, False, False, 0)

        pannel.pack_start(Gtk.VSeparator(), False, False, 10)
        
        
    else:
        vbox.pack_start(Gtk.Label("To comment, Make a channel"), False, False, 30)
        
    return vbox

def send_comment(win, message, claim_id, tb, support=0):


    support = support.get_value()
    if support:
        support_out = fetch.lbrynet("support_create",
                                   {"amount":str(float(round(support, 6))),
                                    "claim_id":claim_id,
                                    "channel_id":win.channel["claim_id"],
                                    "tip":True})

    
        
    # if the user wants to promote FastLBRY
    if win.settings["promote_fast_lbry_in_comments"]:
        message = message + win.settings["promote_fast_lbry_text"] 
    
    # claim_id = win.resolved["claim_id"]
    channel_name = win.channel["name"]
    channel_id = win.channel["claim_id"]

    sigs = sign(message, channel_name)
    if not sigs:
        return
    
    params = {
        "channel_id": channel_id,
        "channel_name": channel_name,
        "claim_id": claim_id,
        "comment": message,
        **sigs
    }
    if support:
        params["support_tx_id"] = support_out["txid"]
        



    if win.commenting[claim_id]["reply"]["to"]:
        params["parent_id"] = win.commenting[claim_id]["reply"]["to"]

        # Make sure to clean that up
        for ch in win.commenting[claim_id]["reply"]["box"].get_children():
            ch.destroy()
        win.commenting[claim_id]["reply"]["to"] = ""

    
    out = comment_request(win, "comment.Create", params)
    i = out["result"] # This will error out if comment is not sent
    tb.set_text("")   # Only if the comment is sent, we clean the text
    # RENDERING THE NEWLY DONW COMMENT INTO THE PAGE
    # TODO: It duplicates it when the comment is actually loaded
    win.commenting[claim_id]["data"]["result"]["items"].append(i)
    print(i["comment_id"])
    box = win.commenting[claim_id]["box"]
    def render(win, box, i):
        render_single_comment(win, box, i)
        box.show_all()
    GLib.idle_add(render, win, box, i)

def sign(data: str = "", channel: str = "", message: str = "Channel to sign data with:", hexdata: str = ""):
    """
    Sign a string or hexdata and return the signatures

    Keyword arguments:
    data -- a string to sign
    channel -- channel name to sign with (e.g. "@example"). Will prompt for one if not given.
    message -- message to give when selecting a channel. Please pass this if not passing channel.
    hexdata -- direct hexadecimal data to sign
    """
    if (not data and not hexdata) or (data and hexdata):
        raise ValueError("Must give either data or hexdata")
    elif data:
        hexdata = data.encode().hex()

    if not channel:
        channel = select(message)

    if not channel.startswith("@"):
        channel = "@" + channel

    try:
        sigs = fetch.lbrynet("channel_sign", {"channel_name":channel, "hexdata":hexdata})
        
        # sigs = check_output([flbry_globals["lbrynet"],
        #                      "channel", "sign",
        #                      "--channel_name=" + channel,
        #                      "--hexdata=" + hexdata])
        # sigs = json.loads(sigs)
        
        return sigs
    except:
        print("Stupid Error")
        return
