#!/bin/env python
# -*- coding: utf-8 -*-
#
# Usage: runlist.py initial_run_no [final_run_no]
#    initial_run_no, final_run_no:
#       range of run numbers to be listed.
#    -np: does not show proton counts

# [inamura 200907] Update to be executable on both Python2 and Python3, to enable 7T magnet

from __future__ import print_function
import sys
import os
import glob
import Manyo as mm
import Manyo.MLF as mmlf
import Manyo.Utsusemi as mu
import utsusemi.ana.Reduction.BaseCommands as BC

ver = float(sys.version_info[0]) + float(sys.version_info[1]) * 0.1
if ver < 2.5:
    from elementtree.ElementTree import ElementTree
else:
    from xml.etree.ElementTree import ElementTree

MAKERUNLIST_KEY_PROTONS = "protons"
MAKERUNLIST_KEY_KICKERS = "kickers"
MAKERUNLIST_KEY_GONIO = "gonio"
#########################################


def usage(argv):
    print("------------------------------------------------------------------------")
    print("Usage  %s [option] <initial_run_no> [<final_run_no>]" % (argv[0]))
    print("       initial_run_no, final_run_no : range of run numbers to be listed.")
    print("------------------------------------------------------------------------")
    print("Option")
    print("       -np          : does not show proton counts")
    print("       -f filename  : saves the list as a text file named filename")
    print("       -r directory : top directory of IROHA2 log folders, like /opt/mlfsoft/data.")
    print("------------------------------------------------------------------------")
    sys.exit(0)

#########################################
# copied from GetMeasBC.py by Y. Inamura


def GetMeasBC(runNo, flag_proton, offset_sec=0.0, isCT8Neutron=False):
    TT = mu.T0TreatToolsNeunet()
    # root_data_dir = os.environ["UTSUSEMI_DATA_DIR"]
    # inst_code = os.environ["UTSUSEMI_SYS_NAME"]
    inst_code = mu.UtsusemiEnvGetInstCode()
    root_data_dir = mu.UtsusemiEnvGetDataDir()
    st_RUNNO = "%3s%06d" % (inst_code, runNo)
    list_DATA_folder = os.listdir(root_data_dir)
    target_dir = ""

    for a_DATA_folder in list_DATA_folder:
        if a_DATA_folder.find(inst_code) < 0:
            continue

        a_path = os.path.join(root_data_dir, a_DATA_folder)
        if os.path.isdir(a_path):
            list_DATA = os.listdir(a_path)
            for a_data_dir in list_DATA:
                if a_data_dir.find(st_RUNNO) == 0:
                    target_dir = os.path.join(a_path, a_data_dir)
                    break
        if target_dir != "":
            break

    if target_dir == "":
        err_message = "There is no data;{}".format(st_RUNNO)
        raise UserWarning(err_message)
    edb_list = glob.glob(target_dir + "/*.edb")
    edb_list.sort()
    first_file = edb_list[0]
    edb_list = glob.glob(target_dir + "/%s*.edb" % (first_file[-24:-7]))
    edb_list.sort()

    if len(edb_list) == 0:
        err_message = "There is no edb data;{}".format(st_RUNNO)
        raise UserWarning(err_message)
    target_edb = mm.MakeStringVector()
    for a_file in edb_list:
        target_edb.append(a_file)

    TT.readOrgEvent(target_edb)
    mpv2 = TT.putMeasPeriodFromT0()

    mpv = mm.MakeDoubleVector()
    for i in range(7):
        mpv.append(mpv2[i])
    for i in range(7):
        mpv.append(mpv2[mpv2.size() - 1 - 6 + i])
    if mpv.size() != 14:
        err_message = "False to get measuring period from Event Data"
        raise UserWarning(err_message)
    start_date = "%04d/%02d/%02d" % (int(mpv[0]), int(mpv[1]), int(mpv[2]))
    start_time = "%02d:%02d:%02d" % (int(mpv[3]), int(mpv[4]), int(mpv[5]))
    end_date = "%04d/%02d/%02d" % (int(mpv[7]), int(mpv[8]), int(mpv[9]))
    end_time = "%02d:%02d:%02d" % (int(mpv[10]), int(mpv[11]), int(mpv[12]))

    proton = "     ---  "
    kicker = "     ---  "
    if flag_proton == 0:  # does not show proton counts
        pass
    else:  # show proton counts
        #        print "NormByBeamCurrent(runNo=%d)" % runNo
        #        print "     begin date and time = ",start_date," ",start_time
        #        print "       end date and time = ",end_date," ",end_time
        if flag_proton == 1 or flag_proton == 3:
            bc, ratio, org_bc = BC.getBeamCurrentWithCorrectRatio(
                start_date, start_time, end_date, end_time, offset_sec, isCT8Neutron)
            proton = "%14.4f" % (bc)
        if flag_proton == 2 or flag_proton == 3 or flag_proton == 4:
            kk = TT.PutT0Index()
            kicker = "%10d" % (int(kk.size()))
        if flag_proton == 4:
            bc, ratio, org_bc = BC.getBeamCurrentWithCorrectRatio(
                start_date, start_time, end_date, end_time, offset_sec, isCT8Neutron)
            proton = "%14.4f %14.4f %10g" % (bc, org_bc, ratio)
    del TT
    return (runNo, start_date, start_time, end_date, end_time, proton, kicker)

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


def MakeRunList(argv):

    Output = []  # list where the output is stored

    # header of the output
    # Output.append("  run#           start                 end              protons     T_A    T_B     gonio")

    argc = len(argv)  # number of argument
    if (argc < 2):
        usage(argv)  # show help and exit

    flag_proton = 1
    offset_sec = 0.0
    # analysis arguments
    output_name = ""
    data_folder = "/opt/mlfsoft/data"
    devname_temp = "LS340"
    devname_gonio = "Gonio-1"

    is7TmagnetTemp = False
    is7TmagnetGonio = False
    isLS336Temp = False
    isHe3TLGonio = False
    isHe3TLTemp = False
    isCRY3HETemp = False
    paramname_7Tmagnet_dict = {"EA": "SIMSTEP_stsAngle",
                               "SA": "SIMSTEP_prmAngle"}  # Encoder Angle and Set Angle
    paramname_7Tmagnet_gonio = "SIMSTEP_stsAngle"

    init_no = -1
    fin_no = -1
    ind = 1
    isCT8Neutron = False
    while(True):
        if argv[ind] == "-np":
            flag_proton = 0
        elif argv[ind] == "-p":
            flag_proton = 1
        elif argv[ind] == "-k":
            flag_proton = 2
        elif argv[ind] == "-pk" or argv[ind] == "-kp":
            flag_proton = 3
        elif argv[ind] == "-a" or argv[ind] == "-all":
            flag_proton = 4
        elif argv[ind] == "-f":
            if ind == (len(argv) - 1):
                usage(argv)
            ind += 1
            output_name = argv[ind]
        elif argv[ind] == "-r":
            if ind == (len(argv) - 1):
                usage(argv)
            ind += 1
            data_folder = argv[ind]
        elif argv[ind] == "-os":
            if ind == (len(argv) - 1):
                usage(argv)
            ind += 1
            offset_sec = float(argv[ind])
        elif argv[ind] == "-T":
            if ind == (len(argv) - 1):
                usage(argv)
            ind += 1
            devname_temp = argv[ind]
            # if dev is 7T magnet
            if devname_temp.upper().find("7TMAG") >= 0:
                is7TmagnetTemp = True
            elif devname_temp.find("336") >= 0:
                isLS336Temp = True
            elif devname_temp.upper().find("HE3TL") >= 0:
                isHe3TLTemp = True
            elif devname_temp.upper().find("CRY3HE") >= 0:
                isCRY3HETemp = True
            else:
                pass

        elif argv[ind] == "-G":
            if ind == (len(argv) - 1):
                usage(argv)
            ind += 1
            devname_gonio = argv[ind]
            # if dev is 7T magnet
            if devname_gonio.upper().find("7TMAG") >= 0:
                is7TmagnetGonio = True
                v = devname_gonio.split("-")
                if len(v) == 2:
                    devname_gonio = v[0]
                    if v[1] in ["EA", "SA"]:
                        paramname_7Tmagnet_gonio = paramname_7Tmagnet_dict[v[1]]
                    else:
                        raise UserWarning(
                            "MakeRunList 7Tmagnet Gonio argument is invalid : -EA(Encoder Angle) or -SA(Set Angle)")
                elif len(v) == 1:
                    devname_gonio = v[0]
                else:
                    raise UserWarning(
                        "MakeRunList 7Tmagnet Gonio argument is invalid")
            elif devname_gonio.upper().find("HE3TL") >= 0:
                isHe3TLGonio = True
            else:
                pass

        elif argv[ind] == "-CT8n":  # if use CT8Neutron
            isCT8Neutron = True
        else:
            if init_no < 0:
                init_no = int(argv[ind])
            else:
                fin_no = int(argv[ind])

        ind += 1
        if ind >= len(argv):
            break

    if init_no < 0:
        usage(argv)
    if fin_no < 0:
        fin_no = init_no

    run_no = init_no  # run number

    if isCT8Neutron:
        proton_source = "CT8n"
    else:
        proton_source = " CT9"

    if flag_proton == 0 or flag_proton == 1:
        Output.append("  run#           start                 end              %s(%s)      T_A    T_B      %s"
                      % (MAKERUNLIST_KEY_PROTONS, proton_source, MAKERUNLIST_KEY_GONIO))
    elif flag_proton == 2:
        Output.append("  run#           start                 end                %s      T_A    T_B      %s"
                      % (MAKERUNLIST_KEY_KICKERS, MAKERUNLIST_KEY_GONIO))
    elif flag_proton == 3:
        Output.append("  run#           start                 end                %s    %s(%s)      T_A    T_B    %s"
                      % (MAKERUNLIST_KEY_KICKERS, MAKERUNLIST_KEY_PROTONS, proton_source, MAKERUNLIST_KEY_GONIO))
    elif flag_proton == 4:
        Output.append("  run#           start                 end           %s        %s           %4s      ratio      T_A     T_B     %s"
                      % (MAKERUNLIST_KEY_KICKERS, MAKERUNLIST_KEY_PROTONS, proton_source, MAKERUNLIST_KEY_GONIO))

    sys_name = mu.UtsusemiEnvGetInstCode()
    while(True):
        # xml file where the experimental condition is stored
        run_number_wild = "%s%06d_*" % (sys_name, run_no)
        # Search /data/SIK, /data/SIK00, ..., /data/SIK*
        run_folder_list = glob.glob(os.path.join(data_folder, sys_name + "*"))
        run_folder_list.sort()
        run_folder = ""
        run_number_list = []
        # a_run_folder is /data/SIK, /data/SIK00, /data/SIK01, ...
        for a_run_folder in run_folder_list:
            # find /data/SIK*/SIK000000_YYYYMMDD
            run_number_list.extend(
                glob.glob(os.path.join(a_run_folder, run_number_wild)))
            if len(run_number_list) != 0:
                run_folder = a_run_folder
                # break
        if run_folder == "":
            raise UserWarning("Run folder not found : {}".format(run_folder))

        if len(run_number_list) != 0:
            fullpath = ""
            for a_run_num_path in run_number_list:
                tmppath = os.path.join(
                    a_run_num_path, "params", ("run%06d.xml" % (run_no)))
                if os.path.exists(tmppath):
                    fullpath = tmppath
                    break
            if fullpath == "":
                raise UserWarning("Not found run{:06d}.xml".format(run_no))

            tt = mmlf.BoostXmlParser()
            tt.Load(fullpath)
            # gonio_path="runInfo/paramsList/devParam,name:%s/params/param/th"%(devname_gonio)
            # temp_path="runInfo/paramsList/devParam,name:%s/params/tmpcnt"%(devname_temp)
            runno_path = "runInfo/runNo"
            runno = int(tt.PutContent(runno_path))

            # read temperature
            temp_a = ""
            temp_b = ""
            # if dev is 7T magnet
            if is7TmagnetTemp:
                tempV_path = "runInfo/measRslt/devLog,devName:%s/devStatus/params/param/LS340_stsTempVTI" % (
                    devname_temp)
                tempS_path = "runInfo/measRslt/devLog,devName:%s/devStatus/params/param/LS340_stsTempSample" % (
                    devname_temp)
                if not tt.hasPath(tempV_path):  # if not found the tag of the old version params.xml from 7T magnet IROHA2
                    tempV_path = "runInfo/measRslt/devLog,devName:{}/devStatus/params/param/LS340a_stsTempVTI".format(devname_temp)
                    tempS_path = "runInfo/measRslt/devLog,devName:{}/devStatus/params/param/LS340b_stsTempSample".format(devname_temp)
                    if not tt.hasPath(tempV_path):
                        raise UserWarning("Not found 7TMagnet Temperature tag ({})".format(tempV_path))
                # read temperature VTI
                tempV_cnt = tt.PutContent(tempV_path)
                if tempV_cnt == "":
                    temp_a = "  --- "
                else:
                    temp_a = "%6.2f" % (float(tempV_cnt))

                # read temperature Samplpe
                tempS_cnt = tt.PutContent(tempS_path)
                if tempS_cnt == "":
                    temp_b = "  --- "
                else:
                    temp_b = "%6.2f" % (float(tempS_cnt))

                Output[0] = Output[0].replace("  T_A", "T_VTI")
                Output[0] = Output[0].replace("   T_B", "T_Samp")
            elif isLS336Temp:
                devname_temp_list = devname_temp.split(",")
                temp_path = "runInfo/measRslt/devLog,devName:%s/devStatus/params/param" % (
                    devname_temp_list[0])
                temp_kelvin_dic = {"A": "kelvinA", "B": "kelvinB", "C": "kelvinC", "D": "kelvinD",
                                   "D2": "kelvinD2", "D3": "kelvinD3", "D4": "kelvinD4", "D5": "kelvinD5"}

                temp1 = ""
                temp2 = ""
                if len(devname_temp_list) == 1:
                    temp1 = tt.PutContent(temp_path + "/" + temp_kelvin_dic["A"])
                    temp2 = tt.PutContent(temp_path + "/" + temp_kelvin_dic["B"])
                elif len(devname_temp_list) == 2:
                    if devname_temp_list[1].upper() in temp_kelvin_dic:
                        Output[0] = Output[0].replace(
                            "  T_A", temp_kelvin_dic[devname_temp_list[1].upper()])
                        Output[0] = Output[0].replace("   T_B", "None")
                    else:
                        raise UserWarning(
                            "Given senser {} is invalid".format(devname_temp_list[1]))
                    temp1 = tt.PutContent(
                        temp_path + "/" + temp_kelvin_dic[devname_temp_list[1].upper()])
                    temp2 = ""
                elif len(devname_temp_list) == 3:
                    if (devname_temp_list[1].upper() in temp_kelvin_dic) and (devname_temp_list[2].upper() in temp_kelvin_dic):
                        Output[0] = Output[0].replace(
                            "  T_A", temp_kelvin_dic[devname_temp_list[1].upper()])
                        Output[0] = Output[0].replace(
                            "  T_B", temp_kelvin_dic[devname_temp_list[2].upper()])
                    else:
                        raise UserWarning("Given senser {} or {} is invalid".format(
                            devname_temp_list[1], devname_temp_list[2]))
                    temp1 = tt.PutContent(
                        temp_path + "/" + temp_kelvin_dic[devname_temp_list[1].upper()])
                    temp2 = tt.PutContent(
                        temp_path + "/" + temp_kelvin_dic[devname_temp_list[2].upper()])
                else:
                    raise UserWarning("ERROR for LS336 ")
                if temp1 != "":
                    if float(temp1) < 10.0:
                        temp_a = "{:6.4f}".format(float(temp1))
                    elif float(temp1) < 100.0:
                        temp_a = "{:6.3f}".format(float(temp1))
                    else:
                        temp_a = "{:6.2f}".format(float(temp1))
                if temp2 != "":
                    if float(temp2) < 10.0:
                        temp_b = "{:6.4f}".format(float(temp2))
                    elif float(temp2) < 100.0:
                        temp_b = "{:6.3f}".format(float(temp2))
                    else:
                        temp_b = "{:6.2f}".format(float(temp2))
            elif isHe3TLTemp:
                temp_a_path = "runInfo/measRslt/devLog,devName:%s/devStatus/params/param/stsDM00512" % ("Shin-TL")
                temp_b_path = "runInfo/measRslt/devLog,devName:%s/devStatus/params/param/stsDM00509" % ("Shin-TL")
                # Read Temperature from run.xml
                temp1 = tt.PutContent(temp_a_path)
                temp2 = tt.PutContent(temp_b_path)
                if temp1 != "":
                    if float(temp1) < 10.0:
                        temp_a = "{:6.4f}".format(float(temp1))
                    elif float(temp1) < 100.0:
                        temp_a = "{:6.3f}".format(float(temp1))
                    else:
                        temp_a = "{:6.2f}".format(float(temp1))
                if temp2 != "":
                    if float(temp2) < 10.0:
                        temp_b = "{:6.4f}".format(float(temp2))
                    elif float(temp2) < 100.0:
                        temp_b = "{:6.3f}".format(float(temp2))
                    else:
                        temp_b = "{:6.2f}".format(float(temp2))
            elif isCRY3HETemp:
                temp_Sample_path = "runInfo/measRslt/devLog,devName:%s/devStatus/params/param/stsDM00509" % ("CRY3HE") # Sample
                temp_3HePot2_path = "runInfo/measRslt/devLog,devName:%s/devStatus/params/param/stsDM00515" % ("CRY3HE") # 3HePot2
                flag_temp_path = tt.PutContent("runInfo/measRslt/devLog,devName:%s/devStatus/params/param/stsDM04562" % ("CRY3HE"))

                # Read Temperature from run.xml
                temp1 = 0.0
                temp2 = 0.0
                if flag_temp_path == "3HePot2":
                    temp1 = float(tt.PutContent(temp_3HePot2_path))
                elif flag_temp_path == "Sample":
                    temp1 = float(tt.PutContent(temp_Sample_path))
                else:
                    temp1 = float(tt.PutContent(temp_Sample_path))
                    temp2 = float(tt.PutContent(temp_3HePot2_path))
                if float(temp1) < 10.0:
                    temp_a = "{:6.4f}".format(float(temp1))
                elif float(temp1) < 100.0:
                    temp_a = "{:6.3f}".format(float(temp1))
                else:
                    temp_a = "{:6.2f}".format(float(temp1))

                temp_b = "----"
                if temp2 != 0.0:
                    if float(temp2) < 10.0:
                        temp_b = "{:6.4f}".format(float(temp2))
                    elif float(temp2) < 100.0:
                        temp_b = "{:6.3f}".format(float(temp2))
                    else:
                        temp_b = "{:6.2f}".format(float(temp2))
            else:
                devname_temp_list = devname_temp.split(",")
                temp_path = "runInfo/measRslt/devLog,devName:%s/devStatus/params/param" % (
                    devname_temp_list[0])
                # print("## [inamura 190128] devname_temp_list=%s, %s, %s"%(tuple(devname_temp_list)))
                sensors_dic = {"A": "temperature_a", "B": "temperature_b", "C": "temperature_c",
                               "D1": "temperature_d1", "D2": "temperature_d2", "D3": "temperature_d3", "D4": "temperature_d4"}
                temp_sensors = [sensors_dic["A"], sensors_dic["B"]]
                temp_sensors_name = ["A", "B"]
                if len(devname_temp_list) > 1 and len(devname_temp_list) <= 3:
                    sensor_list = devname_temp_list[1:]
                    try:
                        for i, a_sensor in enumerate(sensor_list):
                            temp_sensors[i] = sensors_dic[a_sensor]
                            temp_sensors_name[i] = a_sensor
                    except KeyError:
                        raise UserWarning("Given sensers name is invalid.")
                Output[0] = Output[0].replace(
                    "T_A ", "T_%s " % (temp_sensors_name[0]))
                Output[0] = Output[0].replace(
                    "T_B ", "T_%s " % (temp_sensors_name[1]))
                temp_cnt = tt.PutContent(temp_path + "/temperature")
                if temp_cnt == "":
                    temp = "  --- "
                else:
                    temp = "%6.2f" % (float(temp_cnt))

                # read temperature A
                temp_a_cnt = tt.PutContent(temp_path + "/" + temp_sensors[0])
                if temp_a_cnt == "":
                    temp_a = "set_T="
                else:
                    temp_a = "%6.2f" % (float(temp_a_cnt))

                # read temperature B
                temp_b_cnt = tt.PutContent(temp_path + "/" + temp_sensors[1])
                if temp_b_cnt == "":
                    temp_b = temp
                else:
                    temp_b = "%6.2f" % (float(temp_b_cnt))

            # read angle of the gonio
            if is7TmagnetGonio:  # if dev is 7T magnet
                gonio_path = "runInfo/measRslt/devLog,devName:%s/devStatus/params/param/%s" % (
                    devname_gonio, paramname_7Tmagnet_gonio)
            elif isHe3TLGonio:
                gonio_path = "runInfo/measRslt/devLog,devName:%s/devStatus/params/param/rs_angle_pv" % ("Gonio-He3TL")
            else:
                gonio_path = "runInfo/measRslt/devLog,devName:%s/devStatus/params/param/th" % (
                    devname_gonio)
            gonio_cnt = tt.PutContent(gonio_path)
            if gonio_cnt == "":
                gonio = "    ---    "
            else:
                gonio = "%8.3f" % (float(gonio_cnt))

            del tt

            # get proton current
            (runNo, s_date, s_time, e_date, e_time, proton, kicker) = GetMeasBC(
                runno, flag_proton, offset_sec, isCT8Neutron)

            # store the output in the list
            cnt = ""
            if flag_proton == 0 or flag_proton == 1:
                cnt = "%6d   %s %s   %s %s     %s   %s %s   %s" % (
                    runno, s_date, s_time, e_date, e_time, proton, temp_a, temp_b, gonio)
            elif flag_proton == 2:
                cnt = "%6d   %s %s   %s %s     %s   %6s %6s   %8s" % (
                    runno, s_date, s_time, e_date, e_time, kicker, temp_a, temp_b, gonio)
            elif flag_proton == 3:
                cnt = "%6d   %s %s  %s %s      %s   %s   %6s %6s %8s" % (
                    runno, s_date, s_time, e_date, e_time, kicker, proton, temp_a, temp_b, gonio)
            elif flag_proton == 4:
                cnt = "%6d   %s %s  %s %s %s %s   %6s  %6s  %8s" % (
                    runno, s_date, s_time, e_date, e_time, kicker, proton, temp_a, temp_b, gonio)

            Output.append(cnt)

        run_no += 1
        if run_no > fin_no:
            break

    print()  # print blank line
    print("---------------------------------------------------------------------------------------------------------------------------------")
    for out in Output:  # print the output
        print(out)
    print("---------------------------------------------------------------------------------------------------------------------------------")

    # save as text file
    if output_name != "":
        print("     Output file={}".format(output_name))
        fo = open(output_name, "w")
        for out in Output:
            fo.write(out + "\n")
        fo.close()

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


if __name__ == '__main__':
    MakeRunList(sys.argv)
