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

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

# ファイル名: insert_mujoken.py
# 機能: Excel上でユーザが選択した状態変数の各状態における処理にイベントが存在しない場合， 「無条件」という名前のイベントを追加する．
# 関数: insert_mujoken
# 著者名: 山本椋太，若林丈紘

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

import re
import os
import shutil
import sys
from makestm import getAllStatementInScope

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

# 関数名: insert_mujoken
# 機能: 1) ネストの最大深さにある条件式が全て「無条件」であれば削除する．
#           最大深さにある「無条件」以外の条件式が現れるまで上の処理を繰り返す．
#       ※ 条件処理表作成の過程で，処理の列の位置を揃えるために
#          無条件が挿入されることがある．
#          状態遷移表では関数ごとに列の位置が揃えばいいので，
#          深いネストにある余分な無条件を削除しておく．
#       2) イベントのない処理があれば，無条件をイベントとして挿入する．
# 引数
#   parm: 状態変数
#   directory: 解析対象の関数に関する情報がまとめられたディレクトリ

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


def insert_mujoken(param, directory):

    print("\n===============")
    print("= insert_mujoken =")
    print("param: ",param)
    print("directory: ",directory)
    print("===============\n")

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

    # 関数: insert_mujoken
    # 機能： 1) ネストの最大深さにある条件式が全て「無条件」であれば削除する
    #           最大深さにある「無条件」以外の条件式が現れるまで上の処理を繰り返す
    #       ※ 条件処理表作成の過程で，処理の列の位置を揃えるために
    #          無条件が挿入されることがある
    #          状態遷移表では関数ごとに列の位置が揃えばいいので，
    #          深いネストにある余分な無条件を削除しておく
    #       2) イベントのない処理があれば，無条件をイベントとして挿入する

    # INPUT ： idlist2-2.tsv, stlist2.tsv, sequence6-2.tsv
    # OUTPUT: idlist2-3.tsv, sequence6-3.tsv

    # INPUTの入力元 : temp/FUNCTION/ (FUNCTIONは任意の関数名)
    # OUTPUTの出力先: temp/FUNCTION/ (FUNCTIONは任意の関数名)

    # idlist2-2.tsv   : 各関数における条件式の一覧
    # stlist2.tsv     : 各関数における処理の一覧
    # sequence6-2.tsv : 条件式（ID)と，その制御構造に内包されるID，STの一覧

    # idlist2-3.tsv   : idlist2-2.tsvから余分な無条件を削除し，イベントのない処理がある場合に無条件イベントを挿入したファイル
    # sequence6-3.tsv : sequence6-2.tsvから余分な無条件を削除し，イベントのない処理がある場合に無条件イベントを挿入したファイル

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

    # INPUTファイルの読み込み
    out_directory = "temp/" + directory + "/"

    rfile = out_directory + "idlist2_2.tsv"
    fi = open(rfile)
    id_lines = fi.readlines()
    fi.close()

    rfile = out_directory + "stlist2.tsv"
    fi = open(rfile)
    st_lines = fi.readlines()
    fi.close()

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

    fo_id = open(out_directory+"idlist2_3.tsv",'w')
    fo_sq = open(out_directory+"sequence6_3.tsv",'w')

    # ネストの最大深さを取得する
    maxnest = 0
    for id_line in id_lines:
        nest = int(id_line.split("\t")[2])
        if nest > maxnest:
            maxnest = nest


    # 最大深さにある条件式が「無条件」のみであれば削除する
    # ex1)
    # [ID1\tFUNC()\t0, ID2\tif(%%%MJK%%%)\t1,
    #   ID3\tif(%%%MJK%%%)\t2, ID4\tif(hoge)\t1]
    # ↓
    # [ID1\tFUNC()\t0, ID2\tif(%%%MJK%%%)\t1,
    #   ID4\tif(hoge)\t1]
    # # 最大深さ2にある条件式ID3が無条件のみなので削除する
    # # ID3の削除後，最大深さ1にある条件式ID2,4を参照する
    # # ID2,4は無条件以外の条件式が含まれるので削除しない

    # 削除する無条件のID番号をdel_mjkIDsに格納する
    del_mjkflg = False
    del_mjkIDs = []
    for m_nest in range(maxnest,1,-1):
        temp_del_mjkIDs = []
        for i,id_line in enumerate(id_lines):
            temp = id_line.split("\t")
            id = temp[0]
            code = temp[1]
            nest = int(temp[2])

            if nest == m_nest:
                if "%%%MJK%%%" not in code:
                    del_mjkflg = True
                else:
                    temp_del_mjkIDs.append(id)
        if del_mjkflg == True:
            break
        else:
            del_mjkIDs.extend(temp_del_mjkIDs)


    # id_linesからdel_mjkIDに格納される無条件を削除して
    # IDを振り直す
    # 振り直し前後のIDをpre_post_idsに格納する
    pre_post_ids = []
    newid_lines = []
    idcnt = 1
    for i,id_line in enumerate(id_lines):
        temp = id_line.split("\t")
        id = temp[0]
        code = temp[1]
        nest = temp[2]

        newid = "ID"+str(idcnt)

        newid_line = "\t".join([newid,code,nest])
        if id not in del_mjkIDs:
            newid_lines.append(newid_line)
            idcnt += 1
            if id != newid:
                pre_post_ids.append((id,newid))
    print("pre_post_ids: ",pre_post_ids)


    # pre_post_idsに基づいてsequenceのIDを振り直す
    # 削除されるIDについては，そのIDの呼び出し元に中身を展開する
    # ex2) #ex1の続き
    # [ID1\tID2\tID4\t\n, ID2\tID3\t\n,
    #   ID3\tST1\tST2\t\n, ID4\tST3\t\n]
    # ↓
    # [ID1\tID2\tID4\t\n, ID2\tST1\tST2\t\n, ID4\tST3\t\n]
    new_sequence = []
    replace_IDs = []
    for seq in reversed(sequence):
        ids = seq.split("\t")
        target_id = ids[0]
        called_ids = seq.split("\t",1)[1][:-1]
        #print(target_id,"|",called_ids,"|",replace_IDs)

        #changed_170907
        #for replace_ID in replace_IDs:
        for replace_ID in reversed(replace_IDs):
            for i,idx in enumerate(ids):
                if replace_ID[0] == idx:
                    ids[i] = replace_ID[1]

        new_seq = "\t".join(ids)+"\n"
        if target_id not in del_mjkIDs:
            new_sequence.append(new_seq)
        else:
            replace_IDs.append((target_id, called_ids))

    id_lines = newid_lines
    sequence = new_sequence

    for i, seq in enumerate(sequence):
        row = seq.replace("\t\n","").split("\t")
        line = ""
        for r in row:
            for pre_post_id in pre_post_ids:
                if r == pre_post_id[0]:
                    r = pre_post_id[1]
                    break
            line += r+"\t"
        sequence[i] = line + "\n"
    sequence.reverse()
    sq_lines = sequence

    # ↑ ここまでが機能1) 深いネストにある無条件の削除

    print("idlines: ",id_lines)
    print("sqlines: ",sq_lines)

    # ↓ ここからが機能2) 無条件の挿入

    # 状態変数が条件式に含まれる制御構文の最大ネストを取得
    jotai_maxnest = 0
    for i,id_line in enumerate(id_lines):
        temp = id_line.split("\t")
        code = temp[1]
        nest = int(temp[2])
        if nest > jotai_maxnest and "if(" + param in code:
            jotai_maxnest = nest


    jotaiflg = False #状態変数が含まれる条件式のブロックではTrueになる
    uniform_colflg = False
    jotai_nest = 0
    uniform_nest = 0
    insert_ids = []
    mujoken_insert_cnt = 0
    pre_post_ids = []

    # id_linesに，状態変数を含み，かつネストの深さ1の条件式があれば
    # ネスト1の無条件イベントを挿入する
    # ex3)
    # [ID1\tFUNC()\t0, ID2\tif(jotai_value)\t1]
    # ↓
    # [ID1\tFUNC()\t0, ID2\tif(%%%MJK%%%)\t1,
    # ID3\tif(jotai_value)\t2]
    #
    for i,id_line in enumerate(id_lines):
        temp = id_line.split("\t")
        id = temp[0]
        code = temp[1]
        nest = int(temp[2])

        insert_flg = False
        pre_id = id

        if jotaiflg == True and nest == 1 and "else" not in code:
            jotaiflg = False
            jotai_nest = 0

        if uniform_colflg == True and nest < uniform_nest:
            uniform_colflg = False
            offset = 0
            jotaiflg = False

        if param in code and nest==1 and code[:2] == "if" and jotaiflg == False:

            mujoken_insert_cnt += 1
            insert_idnum = int(id[2:]) + mujoken_insert_cnt - 1
            insert_id = "ID" + str(insert_idnum)
            insert_code = "if(%%%MJK%%%)"
            insert_line = "\t".join([insert_id,insert_code,str(nest)]) + "\n"
            print (insert_line,file=fo_id,end="")
            print (insert_line,"###INSERT###")
            insert_flg = True
            jotaiflg = True

        if "if("+ param in code and nest < jotai_maxnest and jotaiflg == False:

            uniform_nest = nest
            offset = jotai_maxnest - nest
            for i in range(offset):
                mujoken_insert_cnt += 1
                insert_idnum = int(id[2:]) + mujoken_insert_cnt - 1
                insert_id = "ID" + str(insert_idnum)
                insert_code = "if(%%%MJK%%%)"
                insert_line = "\t".join([insert_id,insert_code,str(nest+i)]) + "\n"
                print (insert_line,file=fo_id,end="")
                print (insert_line,"###INSERT###")

            jotaiflg = True
            uniform_colflg = True
            print(code,nest,"UNIFORM")

        new_idnum = int(id[2:]) + mujoken_insert_cnt
        post_id = "ID" + str(new_idnum)

        if insert_flg == True:
            insert_ids.append("ID"+str(new_idnum))

        if jotaiflg == True:
            if uniform_colflg == True:
                nest = nest + offset
            else:
                nest = nest + 1

        newid_line = "\t".join([post_id,code,str(nest)]) + "\n"
        print (newid_line,file=fo_id,end="")

        if (pre_id != post_id):
            pre_post_ids.append((pre_id,post_id))
    fo_id.close()



    # id_linesの変更に合わせてsequenceのID,ST番号を振り直す

    # id_linesの変更に合わせてsequenceのIDをずらす
    # ex4-1) # ex3の続き
    # [ID1\tID2\t\n, ID2\tST1\t\n]
    # ↓
    # [ID1\tID2\t\n, ID3\tST1\t\n]
    for pre_post_id in reversed(pre_post_ids):
        sq_lines = [sq_line.replace(pre_post_id[0], pre_post_id[1]) for sq_line in sq_lines]


    # sequenceのIDをずらしてできた空白行に無条件のsequence行を挿入する
    # ex4-2) # ex4-1の続き
    # [ID1\tID2\t\n, ID3\tST1\t\n]
    # ↓
    # [ID1\tID2\t\n, ID2\tID3\t\n, ID3\tST1\t\n]
    pre_idnum = 0
    for sq_line in sq_lines:
        temp = sq_line.split("\t")
        target_id = temp[0]
        target_idnum = int(target_id[2:])

        if len(insert_ids)>0:
            moved_ids = "\t".join(insert_ids)
            if not(target_id in moved_ids):
                pre_id = "ID" + str(int(insert_ids[0][2:])-1)
                if moved_ids in sq_line:
                    sq_line = sq_line.replace(moved_ids,pre_id)
        else:
            moved_ids = ""

        lines_space = target_idnum - pre_idnum
        if lines_space != 1:
            for i in range(lines_space-1):
                insert_pre_id = "ID"+str(pre_idnum + 1)
                insert_post_id = "ID"+str(pre_idnum + 2)
                if insert_post_id == moved_ids.split("\t")[0]:
                    sq_insert_line = insert_pre_id + "\t" + moved_ids + "\t\n"
                else:
                    sq_insert_line = insert_pre_id + "\t" + insert_post_id + "\t\n"
                pre_idnum += 1
                print (sq_insert_line,file=fo_sq,end="")
                print(sq_insert_line,"###INSERT###")

        pre_idnum += 1
        print (sq_line,file=fo_sq,end="")
    fo_sq.close()


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