class CopyAssembly:
    def __init__(self, args):
        '''
        Verify and store information passed in command-line argumens
        '''
        self.lsst_id = None
        self.site = None
        self.loc = None
        self.conn = None
        self.args = args

        # Must of one of lsstId, number arguments
        if args.lsst_id is not None:
            self.lsst_id = args.lsst_id
        elif args.cmpnt_num is not None:
            self.lsst_id = ''.join([args.htype, '-', args.cmpnt_num])
        else:
            raise NameError('Neither lsstId nor number supplied')

        # if --location option was used, check it has proper syntax
        if (args.siteloc) is not None:
            try:
                self.site, self.loc = (args.siteloc).split(':')
            except:
                print('--location argument of improper form')
                raise

    def formList(self, response, good_types):
        '''
        response is the response from the getHierarchy query
        good_types are the hardware types of interest
        
        Returns a list of dicts, each containing information to be used
        in registering one component
        '''
        outlist = []
        didRoot = False
        print('Good types are ')
        for g in good_types:
            print(g)
        for r in response:
            chtype = r['child_hardwareTypeName']
            if chtype not in good_types:
                print(chtype, ' not in list of hardware types')
                continue
            if r['level'] == '0':
                if not didRoot:
                    dict0 = {}
                    dict0['level'] = 0
                    dict0['found'] = False
                    phtype = r['parent_hardwareTypeName']
                    pexpSN = r['parent_experimentSN']
                    dict0['htype'] = phtype
                    dict0['leaf'] = False
                    try:
                        rootInfos = self.conn.getHardwareInstances(
                            htype=phtype, experimentSN=pexpSN)
                        rootInfo = rootInfos[0]
                        for k in rootInfo:
                            dict0[k] = rootInfo[k]
                        outlist.append(dict0)
                        didRoot = True
                        print("Appended to outlist")
                    except:
                        raise

            print('processing type ', chtype)
            cdict = {}
            cdict['parent'] = r['parent_experimentSN']
            cdict['slotName'] = r['slotName']
            cdict['relationshipName'] = r['relationshipTypeName']
            cdict['level'] = int(r['level']) + 1
            cdict['htype'] = chtype
            cdict['leaf'] = True  #   default assumption
            cexpSN = r['child_experimentSN']
            try:
                infos = self.conn.getHardwareInstances(htype=chtype,
                                                       experimentSN=cexpSN)
                info = infos[0]
                for k in info:
                    cdict[k] = info[k]
                outlist.append(cdict)
                print("Appended to outlist")
            except:
                raise

        print('len of out list is ', len(outlist))
        for cdict in outlist:
            for r in response:
                if r['parent_experimentSN'] == cdict['experimentSN'] and r[
                        'parent_hardwareTypeName'] == cdict['htype']:
                    cdict['leaf'] = False
        return outlist

    def register(self, elt):
        if self.site is None:
            site, location = elt['location'].split(':')
        else:
            site = self.site
            location = self.loc

        newId = self.conn.registerHardware(
            htype=elt['htype'],
            site=site,
            location=location,
            experimentSN=elt['experimentSN'],
            manufacturerId=elt['manufacturerId'],
            manufacturer=elt['manufacturer'],
            model=elt['model'])

    def setReady(self, elt, forReal):
        if forReal:
            self.conn.setHardwareStatus(experimentSN=elt['experimentSN'],
                                        htype=elt['htype'],
                                        status='READY',
                                        reason='Set by copy_assembly')
            print('Set status to READY for component ', elt['experimentSN'])
        else:
            print('Would have set status to READY for component ',
                  elt['experimentSN'])

    def execute(self):
        source_list = []
        args = self.args

        uname = args.u
        if uname is None:
            uname = os.getenv('USER')

        source_db = self.args.source_db
        print('Connecting to database ', source_db)
        self.conn = Connection(uname, source_db, prodServer=True, debug=False)

        rsp = []

        try:
            print("Results from getHardwareHierarchy unfiltered:")
            iDict = 0
            rsp = self.conn.getHardwareHierarchy(experimentSN=self.lsst_id,
                                                 htype=args.htype,
                                                 noBatched='true')

            source_list = self.formList(rsp, args.child_types)
            print('#Components found is ', len(source_list))

            for elt in source_list:
                print('An element: ', elt['experimentSN'],
                      elt['manufacturerId'])
                if elt['level'] > 0:
                    print('     ', elt['parent'], elt['slotName'])

        except Exception as msg:
            print('Query of source db failed with exception: ')
            print(msg)
            sys.exit(1)


### Stuff to be properly indented

# Make new connection to dest db
        print('Connecting to database ', args.dest_db)
        forReal = args.forreal
        if args.forreal:
            print('Continue for real? Y or N?')
            try:
                ans = raw_input('--> ')
            except NameError:
                ans = input('-->  ')

            if ans[0] != 'Y':
                print('Switching to dry-run behavior')
                forReal = False

        self.conn = Connection(uname,
                               args.dest_db,
                               prodServer=True,
                               debug=False)

        # SHOULD check that hardware types exist, but for now just hope for the best
        # Query will fail
        #  we get the wrong answer.)

        # Query dest db to find out which ones exist; create any that don't
        # For now do this one by one.  Could instead make 1 query per htype

        for elt in source_list:
            print('Working on component ', elt['experimentSN'])
            #print('Value for key leaf is: ', elt['leaf'])
            try:
                rs = self.conn.getHardwareInstances(
                    htype=elt['htype'], experimentSN=elt['experimentSN'])
                print('Component found in dest db. No register action')
            except ETClientAPINoDataException:
                print('Did not find corresponding component in dest db')
                if (forReal):
                    self.register(elt)
                else:
                    print('Dryrun.  No attempt to create entry')
                pass
            except:
                raise

            if elt['leaf'] is True:
                self.setReady(elt, forReal)
def PrepareInfo():
    ### Prepare necesarry information from eTraveler
    p = re.compile(r".*CCD")

    connection = Connection(operator="youtsumi",
                            db='Prod',
                            exp='LSST-CAMERA',
                            prodServer=True,
                            localServer=False,
                            appSuffix='',
                            cnfPath='~/.ssh/.etapi.cnf')

    experimentSN = "LCA-10134_Cryostat-0001"
    htype = "LCA-10134_Cryostat"
    results = connection.getHardwareHierarchy(experimentSN=experimentSN,
                                              htype=htype)

    rebs = []
    ccds = []

    for Baylevel in results:
        if Baylevel['child_hardwareTypeName'] not in ('LCA-11021_RTM',
                                                      'LCA-10692_CRTM'):
            continue
        Bayinfo = connection.getHardwareInstances(
            htype=Baylevel['child_hardwareTypeName'],
            experimentSN=Baylevel['child_experimentSN'])[0]
        if Baylevel['child_hardwareTypeName'] == 'LCA-11021_RTM':
            flavor = (Bayinfo["model"].split("-")[2])
        else:
            flavor = "ITL"
        print("#############")
        print(Bayinfo, Baylevel, flavor)
        print("#############")

        sub = connection.getHardwareHierarchy(
            experimentSN=Baylevel["child_experimentSN"],
            htype=Baylevel["child_hardwareTypeName"])

        for areb in sub:
            # REB
            if areb['child_hardwareTypeName'] == 'LCA-13574':
                rebinfo = connection.getHardwareInstances(
                    htype=areb['child_hardwareTypeName'],
                    experimentSN=areb['child_experimentSN'])[0]
                rebs.append({
                    "Bay":
                    Baylevel["slotName"],
                    "Flavor":
                    flavor,
                    "Name":
                    Baylevel['child_experimentSN'],
                    "Slot":
                    areb["slotName"].lower().capitalize(),
                    "slot":
                    areb["slotName"].lower().capitalize(),
                    "SerialNum":
                    rebinfo["manufacturerId"],
                    "RebName":
                    rebinfo["experimentSN"],
                    "path":
                    "R{:02d}".format(
                        int(Baylevel["slotName"].replace("Bay", "")))
                })

            # RSA
            if areb['parent_hardwareTypeName'] == 'LCA-10753_RSA' and (p.match(
                    areb["child_hardwareTypeName"]) is not None):
                sensorinfo = connection.getHardwareInstances(
                    htype=areb['child_hardwareTypeName'],
                    experimentSN=areb['child_experimentSN'])[0]
                ccds.append({
                    "Bay":
                    Baylevel["slotName"],
                    "Flavor":
                    flavor,
                    "Name":
                    areb["child_experimentSN"],
                    "Slot":
                    areb["slotName"],
                    "manSerNum":
                    sensorinfo["manufacturerId"],
                    "path":
                    "R{:02d}/Reb{:01d}/{}".format(
                        int(Baylevel["slotName"].replace("Bay", "")),
                        int(areb["slotName"][1]), areb["slotName"])
                })
            # WGREB
            if areb['child_hardwareTypeName'] in [
                    'LCA-13537',  # WREB
                    'LCA-13540'  # GREB
            ]:
                rebinfo = connection.getHardwareInstances(
                    htype=areb['child_hardwareTypeName'],
                    experimentSN=areb['child_experimentSN'])[0]
                rebs.append({
                    "Bay":
                    Baylevel["slotName"],
                    "Flavor":
                    flavor,
                    "Name":
                    Baylevel['child_experimentSN'],
                    "Slot":
                    "WREB" if areb['child_hardwareTypeName'] == 'LCA-13537'
                    else "GREB",
                    "slot":
                    "RebW" if areb['child_hardwareTypeName'] == 'LCA-13537'
                    else "RebG",
                    "RebName":
                    rebinfo["experimentSN"],
                    "SerialNum":
                    rebinfo["manufacturerId"],
                    "path":
                    "R{:02d}".format(
                        int(Baylevel["slotName"].replace("Bay", "")))
                })
            # CRSA
            print(areb)
            if ( areb['child_hardwareTypeName'] == "ITL-CCD" and areb["parent_hardwareTypeName"] == "LCA-10628" ) or \
               ( areb['child_hardwareTypeName'] == "ITL-Wavefront-CCD" and areb["parent_hardwareTypeName"] == "LCA-10626" ):
                ccdhier = connection.getContainingHardware(
                    htype=areb['child_hardwareTypeName'],
                    experimentSN=areb['child_experimentSN'])
                if areb["parent_hardwareTypeName"] == "LCA-10628":
                    # G
                    slot = (ccdhier[1]["slotName"])
                else:
                    # W
                    slot = "W{}".format((ccdhier[0]["slotName"])[-1])
                sensorinfo = connection.getHardwareInstances(
                    htype=areb['child_hardwareTypeName'],
                    experimentSN=areb['child_experimentSN'])[0]
                ccds.append({
                    "Bay":
                    Baylevel["slotName"],
                    "Flavor":
                    flavor,
                    "Name":
                    areb["child_experimentSN"],
                    "Slot":
                    areb["slotName"],
                    "manSerNum":
                    sensorinfo["manufacturerId"],
                    "path":
                    "R{:02d}/Reb{}/S{}{}".format(
                        int(Baylevel["slotName"].replace("Bay", "")),
                        slot[0].upper(), slot[0].upper(),
                        int(slot[-1]) - 1)
                })

    return rebs, ccds