import re


def pick_units (rdesc, rvalue):
    """Picks rule unit based on rule description and value
       Units are detected by presence of any alias or by keyword guess.
       Optionally, keyword within first 2 words can override unit alias found (strong guess).
       Description is filtered: unit aliases are unified, trailing '[unit]' removed.

    Args:
        rdesc: str
            rule description
        rvlue: str
            rule value


    Returns:
        unit : str
            rule unit
        desc: str
            filtered rule description
    """
    mu = '\u00B5'
    sq = '\u00B2'
    no_unit_values = { # values which imply no unit
        'N/A':'N/A',
        '':'',
        }
    desc_picks = {  # recognized units and their aliases
        'deg'     :['degrees','deg','[deg]','(deg)'],
        'mm'      :['mm','[mm]','(mm)'],
        'mm'+sq   :['mm2','[mm2]','(mm2)','mm^2','[mm^2]','(mm^2)','mmsq'],
        mu+'m'    :['um','[um]','(um)'],
        mu+'m'+sq :['um2','[um2]','(um2)','um^2','[um^2]','(um^2)','umsq'],
        'nm'  :['nm','[nm]','(nm)'],
        }
    guess_keywords = { # keywords related to units
        'deg'     :['angle','angles'],
        mu+'m'    :['length','width','space','spacing','distance','enclosure','enclosed','step','l','w','differ','size','within'],
        mu+'m'+sq :['area'],
        '\-'      :['density']
    }
    allow_guessing     = True # allow guessing unit from keywords
    strong_guess_limit = 2    # keyword guess within first n words trumps found unit alias. 0 - disable.

    if rvalue in no_unit_values:
        return no_unit_values[rvalue],rdesc
    unit = []
    # search desc for unit aliases
    desc_search = re.split(' |_|,|\.|\:|\n|\||"',rdesc)
    for u in desc_picks:
        for alias in desc_picks[u]:
            if alias in desc_search:
                unit.append(u)
                if alias == desc_search[-1]: # remove alias if last word od descrition
                    rdesc = rdesc.replace(alias,'')
                else:                        # otherwise replace with unified unit
                    rdesc = rdesc.replace(alias,u)
    # guess unit from description
    if allow_guessing:
        desc_search = [x.lower() for x in desc_search]
        for u in guess_keywords:
            for k in guess_keywords[u]:
                # strong guess: override if keyowrd in first n words and no similar unit found:
                if k in desc_search[:strong_guess_limit] and not u[1:] in [x[1:] for x in unit]:
                    unit = [u]
                # regular guess: use keywords if no unit found yet
                if not len(unit) and k in desc_search:
                    unit = [u]
    # if more units than one, remove duplicates and join
    unit = " ".join(list(dict.fromkeys(unit)))
    #print ([unit, unit[1:]])
    return unit, rdesc