import os
import sys
import dataclasses

LAMBDA_INDEX=0

TMP_DIR="build"


@dataclasses.dataclass
class fun_name_t:
  name:str
  return_type:str
  params:list
  body:str


# 判断是否需要重新生成
def check_rebuild(dst:str,src:list):
  if(not os.path.exists(dst)):
    return True
  dst_time=os.path.getmtime(dst)
  src_time=[]
  for i in src:
    src_time.append(os.path.getmtime(i))
  src_time.sort()
  if(src_time[-1]>dst_time):
    return True
  return False

def find_closed(text:str,par:tuple=('(',')')):
  count_left=0
  count_right=0
  for i in range(len(text)):
    if(text[i]==par[0]):
      count_left+=1
    elif(text[i]==par[1]):
      count_right+=1
    if(count_left==0):
      continue
    if(count_left==count_right):
      # print(f"count_left={count_left} count_right={count_right}")
      return i+1
  # print(f"count_left={count_left} count_right={count_right}")
  return 0


# 找到lambda字符
def calc_lambda_text(text:str):
  lambda_list=[]
  while True:
    index=text.find("lambda(")
    if(index==-1):
      break
    # print(f"index={index}")
    lenght=find_closed(text[index:])
    if(lenght>0):
      lambda_list.append(text[index:index+lenght])
      text=text[index+lenght:]
    else:
      break
  return lambda_list


# 根据lambda字符生成函数名
def create_lambda(text:str):
  global LAMBDA_INDEX
  text=text.replace("lambda(","")[:-1] # 去掉lambda和首末括号
  fun_name=f"__lambda_{LAMBDA_INDEX}"
  LAMBDA_INDEX+=1
  return_type=text[:text.find("(")]
  # 有","则至少有两个参数否则可能有一个参数,可能没有
  param_str=text[text.find("(")+1:text.find(")")]
  params=[]
  if(param_str.count(',')>0):
    params=param_str.split(',')
    for i in range(len(params)):
      params[i]=params[i].strip()
  else:
    t_str=param_str.strip()
    if(len(t_str)>0)and(t_str!="void"):
      params.append(t_str)
  body_start=text.find("{")+1
  body_end=find_closed(text,('{','}'))-1
  return fun_name_t(fun_name,return_type,params,text[body_start:body_end])


# 生成lambda展开后的文件 返回新的源文件列表
def search_lambda(src_list:list) -> list:
  for index,item in enumerate(src_list):
    with open(item,encoding='utf-8') as f:
      d=f.read()
      if(d.count("lambda_use")!=1):
        continue
      lam_index=d.find("lambda_use")
      # 如果标签不在一行的开头 视为不使用lambda
      if(lam_index!=0 and d[lam_index-1]!='\n'):
        continue
      # 获取lambda文件名
      base_path=os.path.join(TMP_DIR,os.path.dirname(item))
      if not os.path.exists(base_path):
        os.makedirs(base_path)
      dst_file_name=os.path.join(base_path, os.path.basename(item))
      src_list[index]=dst_file_name
      # 不需要重新生成lambda文件
      if(not check_rebuild(dst_file_name,[item])):
        continue
      lam_list=calc_lambda_text(d)
      lambda_funs=[]
      for lam in lam_list:
        lambda_funs.append(create_lambda(lam))
    print(f"生成 {dst_file_name}")
    with open(dst_file_name,mode='w+',encoding='utf-8') as f:
      lambda_funs_text=""
      for lam,fun in zip(lam_list,lambda_funs):
        lambda_funs_text+=f"static {fun.return_type} {fun.name}({','.join(fun.params)}){'{'}{fun.body}{'}'}\n"
        d=d.replace(lam,fun.name)
      d=d.replace("lambda_use",lambda_funs_text)
      f.write(d)
  return src_list


if __name__=="__main__":
  t=search_lambda(sys.argv[1:])
  print(t)
