import csv
from org.lsst.ccs.scripting import CCS


class CarouselEposTest(object):

    def __init__(self, epos_file, main_subsystem, node_id):
        self.tcpProxy = CCS.attachSubsystem("%s/tcpProxy" % main_subsystem)
        self.epos_dict = self.parse_epos_file(epos_file)
        self.node = int(node_id, base=0)

    def get_value_from_hardware(self, index, subindex):
        index_int = int(index, base=0)
        subindex_int = int(subindex, base=0)
        str_value = self.tcpProxy.sendSynchCommand("readSDO", self.node, index_int, subindex_int)
        return int(str_value)

    @staticmethod
    def filter_comments(text, delim=";"):
        """Filter comments off of text file"""
        for row in text:
            row_data = row.split(delim)[0].strip()
            if row_data:
                yield row_data

    def parse_epos_file(self, epos_file):
        epos_dict = {}
        try:
            with open(epos_file, 'r') as csvfile:
                info = csv.reader(self.filter_comments(csvfile), delimiter=' ')
                for id_, subid, val in info:
                    if id_ not in epos_dict.keys():
                        epos_dict[id_] = {}
                    epos_dict[id_][subid] = val
        except Exception as e:
            print("Got error when loading the EPOS controller mapping, please check the %s file." % epos_file)
            raise e

        return epos_dict

    def check_dictionary(self):
        issues = []
        for index, sub_dict in self.epos_dict.items():
            for subindex, value in sub_dict.items():
                try:
                    current_value = self.get_value_from_hardware(index, subindex)
                except:
                    print("")
                    print("Issue when reading index/subindex ", index, "/", subindex)
                    print("")
                    continue
                expected_value = int(value, base=0)
                if expected_value != current_value:
                    issues.append((index, subindex, expected_value, current_value))
        return issues

    def run(self):
        """Execute the sequence"""
        print(__doc__)

        issues = check_dictionary(self.epos_dict)

        if issues:
            print("")
            print("EPOS Controller configuration got issues:")
            print("----------------------------------------")
            for idx, sidx, expv, curv in issues:
                print("Index %s with subindex %s has a value %s instead of %s" % (idx, sidx, curv, expv))
        else:
            print("EPOS Controller configuration is OK")


if __name__ == "__main__":
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument(
        "epos_file", type=str,
        help="Path to text file containing the controller mapping")
    parser.add_argument(
        "-s", "--subsystem", 
        type=str, choices=["fcs", "carousel-standalone"], default="fcs", 
        help="Name of the running subsystem: 'fcs' or 'carousel-standalone'")
    parser.add_argument(
        "-n", "--node", 
        type=str, 
        help="Node ID of the controller to be checked")
    args = parser.parse_args()

    CarouselEposTest(args.epos_file, args.subsystem, args.node).run()
