package net.sf.cram.cg;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
class Splitter {
static void split(Read.HalfDnb half) {
int sequencePosition = 0;
int skipSequenceLen = 0;
for (CigEl e : half.cgCigElList) {
switch (e.op) {
case '=':
case 'X':
case 'M':
case 'I':
if (skipSequenceLen > 0) {
if (e.len <= skipSequenceLen) {
skipSequenceLen -= e.len;
sequencePosition += e.len;
break;
} else {
half.gcList.add(new CigEl(e.len - skipSequenceLen, 'S'));
e.len -= skipSequenceLen;
sequencePosition += skipSequenceLen;
skipSequenceLen = 0;
}
} else {
half.gcList.add(new CigEl(e.len, 'S'));
}
for (int i = 0; i < e.len; i++) {
half.readBasesBuf.put(half.baseBuf.get(sequencePosition + i));
half.readScoresBuf.put(half.scoreBuf.get(sequencePosition + i));
}
sequencePosition += e.len;
case 'N':
add(half.samCigarElements, e);
break;
case 'P':
case 'D':
if (skipSequenceLen == 0)
add(half.samCigarElements, e);
break;
case 'B':
half.readBasesBuf.position(half.readBasesBuf.position() - e.len);
half.readScoresBuf.position(half.readScoresBuf.position() - e.len);
int startPos = sequencePosition - e.len;
for (int i = 0; i < e.len; ++i) {
byte scoreL = half.scoreBuf.get(startPos + i);
byte scoreR = half.scoreBuf.get(sequencePosition + i);
if (scoreL > scoreR) {
half.readBasesBuf.position(half.readScoresBuf.position() + 1);
half.readScoresBuf.position(half.readScoresBuf.position() + 1);
} else {
half.readBasesBuf.put(half.baseBuf.get(sequencePosition + i));
half.readScoresBuf.put(scoreR);
}
}
for (int i = 0; i < e.len * 2; i++) {
half.gsBuf.put(half.baseBuf.get(startPos + i));
half.gqBuf.put(half.scoreBuf.get(startPos + i));
}
half.gcList.get(half.gcList.size() - 1).len -= e.len;
half.gcList.add(new CigEl(e.len, 'G'));
skipSequenceLen = e.len;
break;
default:
break;
}
}
}
private static final char collapsibleType(char ch) {
switch (ch) {
case 'I':
case 'P':
return 'I';
case 'D':
return 'D';
default:
return 0;
}
}
static LinkedList<CigEl> pack(List<CigEl> list) {
LinkedList<CigEl> result = new LinkedList<CigEl>();
for (CigEl e : list) {
add(result, e);
int prevIndex = result.size() - 1;
while (prevIndex > 0) {
CigEl lastE = result.get(prevIndex);
char lastType = collapsibleType(lastE.op);
if (lastType > 0) {
--prevIndex;
CigEl prevE = result.get(prevIndex);
char prevType = collapsibleType(prevE.op);
if (prevType == 0 || lastType == prevType)
break;
// collapse insertion and deletion and generate 'M'/'N' to
// replace the overlapping part
boolean prevEShorter = prevE.len < lastE.len;
CigEl shortE = prevEShorter ? prevE : lastE;
CigEl longE = !prevEShorter ? prevE : lastE;
longE.len -= shortE.len;
if (longE.op == 'I' || shortE.op == 'I') {
shortE.op = 'M';
} else {
shortE.op = 'N';
}
if (prevE.len == 0) {
result.remove(prevIndex);
break;
} else if (prevIndex > 0) {
CigEl checkE = result.get(prevIndex - 1);
if (checkE.op == prevE.op) {
checkE.len += prevE.len;
result.remove(prevIndex);
} else {
Collections.swap(result, prevIndex, prevIndex + 1);
}
}
} else
break;
}
}
return result;
}
private static final void add(List<CigEl> list, CigEl e) {
add(list, e.len, e.op);
}
private static final void add(List<CigEl> list, int len, char op) {
if (len == 0)
return;
if (!list.isEmpty()) {
CigEl last = list.get(list.size() - 1);
if (last.op == op) {
last.len += len;
return;
}
}
list.add(new CigEl(len, op));
}
}