'Merge a set of VCard lines from a given source into this card.
>>> vc = SimpleVCard(VCardLine(name=\'fn\', value=\'Bjarni\', pid=\'1.2\'),
...                  VCardLine(name=\'email\', value=\'bre@foo\', t=\'1\'),
...                  VCardLine(name=\'email\', value=\'bre@bar\', t=\'2\'),
...                  VCardLine(name=\'clientpidmap\',
...                            value=\'1;thisisauid\'))
>>> vc.merge(\'thisisauid\', [VCardLine(name=\'fn\', value=\'Bjarni\'),
...                         VCardLine(name=\'x-a\', value=\'b\')])
1
>>> vc.get(\'x-a\')[\'pid\']
\'1.3\'
>>> vc.get(\'fn\')[\'pid\']
\'1.2\'
>>> vc.get(\'email\', prefer={\'t\': \'1\'}).value
u\'bre@foo\'
>>> vc.get(\'email\', prefer={\'t\': \'2\'}).value
u\'bre@bar\'
>>> vc.get(\'email\', prefer={\'t\': \'unfindable\'}).value
u\'bre@foo\'
>>> vc.merge(\'otheruid\', [VCardLine(name=\'x-b\', value=\'c\')])
2
>>> vc.get(\'x-b\')[\'pid\']
\'2.1\'
>>> vc.merge(\'thisisauid\', [VCardLine(name=\'fn\', value=\'Inrajb\')])
3
>>> vc.get(\'fn\')[\'pid\']
\'1.4\'
>>> vc.fn
u\'Inrajb\'
>>> vc.get(\'x-a\')
Traceback (most recent call last):
IndexError: ...
>>> print vc.as_vCard()
BEGIN:VCARD
VERSION:4.0
CLIENTPIDMAP:1\;thisisauid
CLIENTPIDMAP:2\;otheruid
EMAIL;T=1:bre@foo
EMAIL;T=2:bre@bar
FN;PID=1.4:Inrajb
X-B;PID=2.1:c
END:VCARD'

def merge(self, src_id, lines):

    if (not lines):
        return
    lines = [l for l in lines if (not (l.name in self.UNREMOVABLE))]
    changes = 0
    with self._lock:
        (src_pid, pidmap, version, is_new) = self.get_pidmap(src_id, create=True)
        if is_new:
            changes += 1
        lines.sort(key=(lambda k: (k.name, k.value)))
        dedup = [lines[0]]
        rank = 0
        def rankit(rank):
            if rank:
                rank += int(dedup[(-1)].get('x-rank', 0))
                dedup[(-1)].set_attr('x-rank', rank)
        for line in lines[1:]:
            if ((dedup[(-1)].name == line.name) and (dedup[(-1)].value == line.value)):
                rank += 1
            else:
                rankit(rank)
                rank = 0
                dedup.append(line)
        rankit(rank)
        lines = dedup
        to_remove = []
        for (ver, ol) in pidmap['lines'][:]:
            match = [l for l in lines if (l and (l.name == ol.name) and (l.value == ol.value))]
            for l in match:
                lines.remove(l)
            if (not match):
                pids = [pid for pid in ol.get('pid', '').split(',') if (pid and (int(pid.split('.')[0]) != src_pid))]
                if pids:
                    ol.set_attr('pid', ','.join(pids))
                    changes += 1
                elif ((not ol.get('pref')) and (ol.name not in ('email',))):
                    self.remove(ol.line_id)
                    changes += 1
        version += 1
        for vcl in lines:
            old = [ol for ol in self.get_all(vcl.name) if (ol.value == vcl.value)]
            for ol in old:
                pids = [pid for pid in ol.get('pid', '').split(',') if (pid and (int(pid.split('.')[0]) != src_pid))]
                pids.append(('%s.%s' % (src_pid, version)))
                ol.set_attr('pid', ','.join(sorted(pids)))
            if (not old):
                vcl.set_attr('pid', ('%s.%s' % (src_pid, version)))
                self.add(vcl)
                changes += 1
    return changes
