
from .sum import Sum
from fastapi import Request, Response
from .blackbox import Blackbox
from injector import singleton, inject
from ..dotchain.runtime.interpreter import program_parser
from ..dotchain.runtime.runtime import Runtime
from ..dotchain.runtime.tokenizer import Tokenizer
from ..dotchain.runtime.ast import Literal
import json
import re


def read_binay(io):
    return Literal(io.read())

def new_map():
    return Literal({})

def set_map_value(map: dict, key, value):
    map[key] = value 
    return map

def jsonfiy(obj):
    return Literal(json.dumps(obj))

def get_map_value(d: dict, key):
    value = d.get(key)
    if value is dict:
        return value
    if value is list:
        return value
    return Literal(value)
def get_map_int(d: dict, key):
    value = d.get(key)
    return Literal(int(value))

@singleton
class Workflow(Blackbox):
    
    @inject
    def __init__(self, sum: Sum) -> None:
        self.sum_blackbox = sum
        self.cost = 0
    
    def __call__(self, *args, **kwargs):
        return self.processing(*args, **kwargs)
    
    def text_to_audio(self, text):
        return Literal(self.text_to_audio_blackbox.processing(text))
    
    def sum(self, *args, **kwargs):
        return Literal(self.sum_blackbox.processing(*args, **kwargs))
    
    def get_cost(self):
        return self.cost
    
    def blackbox_example(self):
        self.cost_increase(10);
        return Literal("Blackbox result")
    
    def cost_increase(self, cost):
        self.cost+=cost
        return self.cost
    
    async def processing(self, *args, **kwargs):
        request: Request = args[0]
        json = await request.json()
        content = None
        mdeia_type = None
        headers = {}
        def set_content(c):
            nonlocal content
            content = c
        def set_media_type(m):
            nonlocal mdeia_type
            mdeia_type = m
        def add_header(key, value):
            nonlocal headers
            headers[key] = value
        script = request.query_params["script"]
        t = Tokenizer()
        t.init(script)
        runtime = Runtime(
            context={"json": json},
            exteral_fun={
                "print": print,
                "new_map": new_map,
                "set_map_value": set_map_value,
                "get_map_value": get_map_value,
                "set_content": set_content,
                "set_media_type": set_media_type,
                "add_header": add_header,
                "sum": self.sum,
                "read_binay": read_binay,
                "jsonfiy": jsonfiy,
                "get_map_int": get_map_int,
                "blackbox_example": self.blackbox_example,
                "get_cost": self.get_cost,
            }
        )
        ast = program_parser(t)
        ast.exec(runtime)
        return Response(content=content, media_type=mdeia_type, headers=headers)
    
    def valid(self, *args, **kwargs) -> bool:
        return super().valid(*args, **kwargs)
    
    async def fast_api_handler(self, request: Request):
        return await self.processing(request)
    
"""
let b = new_map();
set_map(b,"man","good");
let a = new_map();
set_map(a, "hello", "world");
set_map(a, "hello2", b);
set_media_type("application/json");
set_content(jsonfiy(a));
"""