#!/usr/bin/env python
# coding: Shift_JIS

# ##############################

# ファイル名: makestm.py
# 機能: 状態変数が含まれる条件式のネストの内側にある制御構文を，状態遷移表における処理として扱うようにする．
# 関数: separate, delete_ifelse, getAllStatementInScope, getAllStatementInScope2, getAllIDParent, makestm
# 著者名: 山本椋太，若林丈紘

# ##############################

import re
import os.path as path
import sys


# ==のみ考えている
# ==が複数ある場合は考えてない
# 左辺ないし右辺に変数だけの数式が存在する．
### すなわち，if(state == 1) はありうるが，
### if(state+1 == 2)は存在しないこととしている

# ##############################

# 関数名: separate
# 機能: 状態値を取得する．
# 引数
#   val: ※関数中で使用されていない
#   formula: 解析中の文字列

# ##############################

def separate(val, formula):
    formula = formula.replace(" ","")
    if "==" in formula:
        row = formula.split("==")
        if re.search("^[0-9]+",row[0]):
            row[0] = row[0].replace(')', '')
            return row[0]
        else:
            row[1] = row[1].replace(')', '')
            return row[1]
    else:
        if formula == "else":
            return "ELSE"

# ##############################

# 関数名: delete_ifelse
# 機能: ※呼び出し元を確認できなかった
# 引数
#   statement:

# ##############################

def delete_ifelse(statement):
    statement = statement.replace(" ", "")
    if re.match("if\(", statement):
        return statement[3:-1]
    elif re.match("elseif\(", statement):
        return statement[7:-1]
    elif re.match("else", statement):
        return statement[4:-1]

# ##############################

# 関数名: getAllStatementInScope
# 機能: IDを入力すると，そのIDの中にあるSTを根こそぎリストで返す．
# 引数
#   sequence: IDとSTの依存関係がまとめられたファイル
#   tid: IDの識別番号

# ##############################

#IDを入力すると，そのIDの中にあるSTを根こそぎリストで返す．
def getAllStatementInScope(sequence, tid):
    line = sequence[int(tid[2:])-1]
    row = line.split("\t")
    statement = list()
    for r in row[1:]:
        if "ID" in r:
            temp = getAllStatementInScope(sequence, r)
            for t in temp:
                if t == "":continue
                statement.append(t)
        else: statement.append(r)
    i = 0
    while statement.count("") > 0:
        statement.remove("")
    return statement

# ##############################

# 関数名: getAllStatementInScope2
# 機能: IDを入力すると，そのIDの中にあるSTを根こそぎリストで返す．
# 引数
#   sequence: IDとSTの依存関係がまとめられたファイル
#   tid: IDの識別番号

# ##############################

#IDを入力すると，そのIDの中にあるSTを根こそぎリストで返す．
def getAllStatementInScope2(sequence, tid):
    line = sequence[int(tid[2:])-1]
    row = line.split("\t")
    statement = list()
    for r in row[1:]:
        if "ID" in r:
            statement.append(r)
            temp = getAllStatementInScope(sequence, r)
            for t in temp:
                if t == "":continue
                statement.append(t)
        else: statement.append(r)
    i = 0
    while statement.count("") > 0:
        statement.remove("")
    return statement

# ##############################

# 関数名: getAllIDParent
# 機能: STまたはIDを入力すると，そのIDの親を根こそぎリストで返す．
# 引数
#   sequence: IDとSTの依存関係がまとめられたファイル
#   idst: IDもしくはSTの識別番号

# ##############################

#STまたはIDを入力すると，そのIDの親を根こそぎリストで返す．
def getAllIDParent(sequence, idst):
    outlist = list()
    for seq in sequence:
        row = seq.split("\t")
        if idst in row:
#            print(idst,row[0],idst==row[0])
            if idst == row[0]:
                outlist.append(row[0])
                return outlist
            else:
                temp = getAllIDParent(sequence,row[0])
                for t in temp: outlist.append(t)
    return outlist

# ##############################

# 関数名: makestm
# 機能: 状態変数が含まれる条件式のネストの内側にある制御構文を，状態遷移表における処理として扱うようにする．
# 引数
#   param: 状態変数
#   directory: 解析対象の関数に関する情報がまとめられたディレクトリ

# ##############################

def makestm(param,directory):

    print("\n===============")
    print("makestm")
    print("===============\n")

    out_directory = "temp/" + directory + "/"

    fi = open(out_directory+("stm_jotailist.tsv"),"r")
    jotailist = fi.read()[:-1].split("\n")
    fi.close()

    fi = open(out_directory+("stm_idlist2.tsv"),"r")
    idlist = fi.read()[:-1].split("\n")
    fi.close()

    fi = open(out_directory+("stm_sequence2.tsv"),"r")
    sequence = fi.read()[:-1].split("\n")
    fi.close()

    fi = open(out_directory+("stm_stlist2.tsv"),"r")
    stlist = fi.read()[:-1].split("\n")
    fi.close()

    fi = open(out_directory+("stm_eventlist.tsv"),"r")
    eventlist = fi.read()[:-1].split("\n")
    fi.close()

    fi = open(out_directory+("stm_jotaivalue.tsv"),"r")
    jotaivalue = fi.read()[:-1].split("\n")
    fi.close()

    print("------------------")
    print(jotailist)

    print("------------------")
    print(idlist)

    # 状態列の(見出しの)作成．
    # ただし，ELSEを考慮して状態値の重複は削除せず（ELSEの値の範囲がわからなくなる），
    # 同じ理由でsortもかけない．

    # まず，状態判定を削除してしまったことでずれたままのIDを取得する．
    temp_jotaicol = list()
    for jl in jotailist:
        row = jl.split('\t')
        jotaival = separate('[0-9]+', row[1])
        temp_jotaicol.append([row[1],row[2]])

    # ずれたIDをもとのidlistを使って，補正する．
    fi = open(out_directory+('stm_idlist.tsv'), 'r')
    old_idlist = fi.read()[:-1].split('\n')
    fi.close()

    rowcnt = 0
    jotaicol = list()
    for oi in old_idlist:
        print('oi:', oi)
        row = oi.split('\t')
        refer = [row[1],row[2]]
        if temp_jotaicol[rowcnt] == refer:
            jotaival = separate('[0-9]+', row[1])
            jotaicol.append([row[0],jotaival])
            rowcnt += 1
            if len(temp_jotaicol) == rowcnt: break
    print('col:', jotaicol)

    # 状態列の(見出しの)作成．
    # ただし，ELSEを考慮して状態値の重複は削除せず（ELSEの値の範囲がわからなくなる），
    # 同じ理由でsortもかけない．

    eventrow = list()
    for el in eventlist:
        row = el.split('\t')
        eventrow.append([row[0],row[1]])
    print('row:', eventrow)

    #古いsequenceを読み込み，依存関係を保管する．
    fi = open(out_directory+("stm_sequence.tsv"),"r")
    old_sequence = fi.read()[:-1].split("\n")
    fi.close()

    fo = open(out_directory + "stm_tablecolumn.tsv", "w")
    fi = open(out_directory+("stm_stlist.tsv"),"r")
    old_stlist = fi.read()[:-1].split("\n")
    fi.close()

    funcname = idlist[0].split('\t')[1]
    table = [[' ', ' '], [' ', ' ']]

    # 関数列の作成とイベント列の作成
    for i in range(len(eventrow)):
        table[0].append(funcname)
        table[1].append(eventrow[i][1])

    # 状態値列毎に作成
    rev_eventrow = eventrow[:]
    rev_eventrow.reverse()
    for i in range(len(jotaicol)):
        if i == 0: table.append([param, jotaicol[i][1]])
        else: table.append(['$$NONE$$', jotaicol[i][1]])
        col = jotaicol[i][0]
        parent = getAllIDParent(old_sequence, col)[1:]
        print(col, parent)
        for j in range(len(eventrow)):
            row = eventrow[j][0]
            if row in parent:
                processlist = getAllStatementInScope2(old_sequence,col)
                outstr = ''
                indent = 0
                nowdepth = 0
                for pl in processlist:
                    if 'ID' in pl:
                        temp = old_idlist[int(pl[2:])-1] #oldidlist の split してない生データ
                        temp = temp.split('\t')
                        outstr += ('  '*indent) + temp[1] + '$$NL$$'
                    else: outstr += old_stlist[int(pl[2:])-1] + '$$NL$$'
                outstr = outstr[:-6]
                checkstr = outstr.replace('$$NL$$', '')
                checkstr = checkstr.replace('##NONE##', '')
                checkstr = checkstr.replace('$$$NONE$$$', '')
                checkstr = checkstr.replace('if(%%%MJK%%%)', '')
                if checkstr == '': outstr = 'N/A'
                outstr = outstr.replace('if(%%%MJK%%%)$$NL$$','')
                outstr = outstr.replace('if(%%%MJK%%%)','')
                table[-1].append(outstr)
            else:
                table[-1].append('N/A')
    for tab in table:
        for t in tab[:-1]:
            print(t, end='\t',file=fo)
            print(t, end='\t')
        print(tab[-1],file=fo)
        print(tab[-1])
    fo.close()
    return


    """

    parent_of_st = list()
    #各処理に対して上位条件式を付与する
    for i, st in enumerate(stlist):
        temp = getAllIDParent(sequence, "ST"+str(i+1))[1:]
        temp.append("ST"+str(i+1))
        parent_of_st.append(temp)
    print ("PARENT_OF_ST",parent_of_st)
 #   input()
    state_deepest_nest = 0
    #状態判定の最大ネストを求める．
    for jl in jotailist:
        row = jl.split("\t")
        nest = int(row[2])
        if nest > state_deepest_nest:
            state_deepest_nest = nest
#    print(state_deepest_nest)
#    input()
#    print(parent_of_st)
#    input()
    #処理化するイベントの展開
    #ただし，状態変数を含む条件式はすべて同一階層のネストであると仮定する．
    #この仮定における理由は，無条件の追加による．
    prestate = ""
    prestate_event = list()
    event_deepest_nest = state_deepest_nest-1
    print ("state_deepest_nest",state_deepest_nest)

    for i,pos in enumerate(parent_of_st):
        rpos = pos[:-1]
        rpos.reverse()
        for j,p in enumerate(rpos):
            row = idlist[int(p[2:])-1].split("\t")

            #状態変数の条件式よりも深いネストの条件に対する処理
            if int(row[2]) > state_deepest_nest:
                temp = getAllStatementInScope(sequence, p)
                index = int(temp[0][2:]) - 1

                stlist[index] = row[1]+"{$$NL$$  "+stlist[index]

                if len(stlist) > 1:
                    k = index+1
                    while k < int(temp[-1][2:]):
                        stlist[k] = "  "+stlist[k]
                        k += 1

                stlist[int(temp[-1][2:])-1] += "$$NL$$}"

                parent_of_st[i].remove(row[0])

            #状態変数の更新のif文(と同階層も含む)
            #ここで直前の条件式を拾う

            elif int(row[2]) == state_deepest_nest and \
                    row[1] != prestate and \
                        not (re.match("^else*\s$",row[1])):

                print(parent_of_st[i],j-1)

                # (changed 2017_0325_wakabayashi)
                temp = parent_of_st[i][j-1]
                #temp = parent_of_st[i][0]
                if temp not in prestate_event:
                    prestate = row[1]
                    prestate_event.append(temp)

    #            pass #あとで必要なら考えます

    print("prestate_event")
    print(prestate_event)
    print(stlist)
    print("pos::\n",parent_of_st)

    tablecolumn = list()
    events = list()
    eventid = list()
    eachevent_stament = list()

    for i in range(0,event_deepest_nest+1):
        tablecolumn.append([''])

    #表の列のとりあえず作成

    #stだったら統合してしまう
    #本来なら親のif文を確認するべきである
    allstatement = True
    for pe in prestate_event:
        if 'ID' in pe:
            allstatement = False
            continue
    if allstatement == True:
        print (prestate_event)
        temp = prestate_event[0]
        prestate_event=list()
        prestate_event.append(temp)
    print(prestate_event)


    for el in eventlist:
        row = el.split("\t")
        eventid.append(row[0])
    #print(tablecolumn)
    #input()
    for jv in jotaivalue:
        tablecolumn.append([jv])
    #print(tablecolumn)
    #print("events")
    #print(eventid)
    #print(eachevent_stament)
    #input()

    jotaiid = list()
    for jl in jotailist:
        jotaiid.append(jl.split("\t")[0])


    print("%%%%%%%%%%%%%%%%%")
    #print(parent_of_st)
    used_ps = []
    else_flg = False

    for pos in parent_of_st:
        p_col = 0
        for pnum,p in enumerate(pos):
            print("p",p)
            #多階層に未対応
            #厳密には，下記形式のみ対応
            #  nest == 1 then EVENT
            #  nest == 2 then STATE
            #  nest == 3 then Converted

            if p == prestate_event:
                p_row=prestate_event.index(p)
            #(added 2017_0321_wakabayashi)
            if p in eventid:
                for event in eventlist:
                    if p == event.split("\t")[0] and not(p in used_ps):
                        p_col = int(event.split("\t")[2]) -1

                        os = event.split("\t")[1]
                        print("EVENT,p_col",p,p_col)
                        tablecolumn[p_col].append(os)
                        print("APPEND",p,p_col)
                        used_ps.append(p)

            elif p in jotaiid:
                # (changed 2017_0324_wakabayashi)
                # 状態elseまで処理が達した後，初めの状態値に戻る場合は，
                # それまで参照した状態値をすべてjotaiidからpopしておく
                #
                # p_col=jotaiid.index(p)+1
                #
                if else_flg == True:
                    jotaiid = jotaiid[jotaiid.index(p):]
                    else_flg = False
                p_col=jotaiid.index(p)+event_deepest_nest

                for jl in jotailist:
                    id = jl.split("\t")[0]
                    jotai = jl.split("\t")[1]
                    if id == p and re.match("^else*\s$",jotai) :
                        else_flg = True
                        print("rightend",jotai,jotailist)

                #変更ここまで

            elif "ST" in p:
                os = stlist[int(p[2:])-1]
                tablecolumn[p_col].append(os)


    maxrows = 0
    for tc in tablecolumn:
        length = len(tc)
        if length > maxrows: maxrows=len(tc)
    for j, tc in enumerate(tablecolumn):
        #(changed 2017_0321_wakabayashi)
        if j < event_deepest_nest:
        #if j == 0:
            print(tablecolumn,j)
            while len(tablecolumn[j]) < maxrows:
                tablecolumn[j].append(tablecolumn[j][1])
        else:
            while len(tablecolumn[j]) < maxrows:
                tablecolumn[j].append("")

    #fo = open("TSV_Result/test.tsv","w")
    #for j,t in enumerate(tablecolumn[0]):
    #    k = 0
    #    outstr = ""
    #    while k < len(tablecolumn):
    #        print(tablecolumn)
    #        input()
    #        outstr += tablecolumn[k][j] + "\t"
    #        k += 1
    #    print(outstr[:-1],end="\r\n",file=fo)
    #fo.close()

    print("%%%%%%%%%%%%%%%%%")

    #input()

    """
    """
    for pos in parent_of_st:
        for p in pos:
            #多階層に未対応
            #厳密には，下記形式のみ対応
            #  nest == 1 then EVENT
            #  nest == 2 then STATE
            #  nest == 3 then Converted

            if p in prestate_event:
                p_row = prestate_event.index(p)
            elif p in jotaiid:
                p_col = jotaiid.index(p)+1
            elif "ST" in p:
                tablecolumn[p_col].append(p)
    """
    """


    #        if p in
    print("\n#############")
    print(tablecolumn)

    for i, tc in enumerate(tablecolumn):
        #(changed 2017_0321_wakabayashi)
        #if i == 1:
        #    tablecolumn[1].insert(0,param)
        if i == event_deepest_nest:
            tablecolumn[event_deepest_nest].insert(0,param)
        else:
            tablecolumn[i].insert(0,' ')


    temp = ['','']

    #本来は，複数関数を考慮するべき
    print(idlist)
    funcname = idlist[0].split('\t')[1]
    for i in range(0,len(tablecolumn[0])-2):
        temp.append(funcname)

    tablecolumn.insert(0,temp)
    print("TABLECOLUMN",tablecolumn)

    #(added 2017_0328_wakabayashi)
    fo = open(out_directory + "stm_tablecolumn.tsv", "w")
    for tc in tablecolumn:
        tc = ["###NONE###" if tc_element == "" else tc_element for tc_element in tc]
        print("\t".join(tc), file=fo)
    """

if __name__=='__main__':
    makestm(sys.argv[1],sys.argv[2],sys.argv[3])
