void
MSTLLogicControl::WAUTSwitchProcedure_Stretch::stretchLogic(SUMOTime step, SUMOTime startPos, SUMOTime allStretchTime) {
    unsigned int currStep = myTo->getIndexFromOffset(startPos);
    SUMOTime durOfPhase = myTo->getPhase(currStep).duration;
    SUMOTime remainingStretchTime = allStretchTime;
    SUMOTime StretchTimeOfPhase = 0;
    unsigned int stretchUmlaufAnz = (unsigned int) TplConvert::_2SUMOReal(myTo->getParameterValue("StretchUmlaufAnz").c_str());
    SUMOReal facSum = 0;
    int areasNo = getStretchAreaNo(myTo);
    for (int x = 0; x < areasNo; x++) {
        StretchBereichDef def = getStretchBereichDef(myTo, x + 1);
        facSum += def.fac;
    }
    facSum *= stretchUmlaufAnz;

    //switch to startPos and stretch this phase, if there is a end of "bereich" between startpos and end of phase
    SUMOTime diffToStart = getDiffToStartOfPhase(*myTo, startPos);
    for (int x = 0; x < areasNo; x++) {
        StretchBereichDef def = getStretchBereichDef(myTo, x + 1);
        SUMOTime end = TIME2STEPS(def.end);
        SUMOTime endOfPhase = (startPos + durOfPhase - diffToStart);
        if (end <= endOfPhase && end >= startPos) {
            SUMOReal fac = def.fac;
            SUMOReal actualfac = fac / facSum;
            facSum = facSum - fac;
            StretchTimeOfPhase = TIME2STEPS(int(STEPS2TIME(remainingStretchTime) * actualfac + 0.5));
            remainingStretchTime = allStretchTime - StretchTimeOfPhase;
        }
    }
    if (facSum == 0) {
        WRITE_WARNING("The computed factor sum in WAUT '" + myWAUT.id + "' at time '" + toString(STEPS2TIME(step)) + "' equals zero;\n assuming an error in WAUT definition.");
        return;
    }
    durOfPhase = durOfPhase - diffToStart + StretchTimeOfPhase;
    myTo->changeStepAndDuration(myControl, step, currStep, durOfPhase);

    currStep = (currStep + 1) % (int)myTo->getPhases().size();
    // stretch all other phases, if there is a "bereich"
    while (remainingStretchTime > 0) {
        for (unsigned int i = currStep; i < myTo->getPhases().size() && remainingStretchTime > 0; i++) {
            durOfPhase = myTo->getPhase(i).duration;
            SUMOTime beginOfPhase = myTo->getOffsetFromIndex(i);
            SUMOTime endOfPhase = beginOfPhase + durOfPhase;
            for (int j = 0; j < areasNo && remainingStretchTime > 0; j++) {
                StretchBereichDef def = getStretchBereichDef(myTo, j + 1);
                SUMOTime end = TIME2STEPS(def.end);
                SUMOReal fac = def.fac;
                if ((beginOfPhase <= end) && (endOfPhase >= end)) {
                    SUMOReal actualfac = fac / facSum;
                    StretchTimeOfPhase = TIME2STEPS(int(STEPS2TIME(remainingStretchTime) * actualfac + 0.5));
                    facSum -= fac;
                    durOfPhase += StretchTimeOfPhase;
                    remainingStretchTime -= StretchTimeOfPhase;
                }
            }
            myTo->addOverridingDuration(durOfPhase);
        }
        currStep = 0;
    }
}
void
MSTLLogicControl::WAUTSwitchProcedure_Stretch::cutLogic(SUMOTime step, unsigned int pos, size_t deltaToCut) {
    MSSimpleTrafficLightLogic *LogicTo = (MSSimpleTrafficLightLogic*) myTo;
    unsigned int startPos = pos;
    unsigned int actStep = LogicTo->getIndexFromOffset(startPos);
    size_t allCutTime = deltaToCut;
    // switches to startPos and cuts this phase, if there is a "Bereich"
    int noBereiche = getStretchBereicheNo(myTo);
    size_t toCut = 0;
    for (int i=0; i<noBereiche; i++) {
        StretchBereichDef def = getStretchBereichDef(myTo, i+1);
        unsigned int begin = (unsigned int) def.begin;
        unsigned int end = (unsigned int) def.end;
        size_t stepOfBegin = LogicTo->getIndexFromOffset(begin);
        if (stepOfBegin == actStep)	{
            if (begin < startPos) {
                toCut = end - startPos;
            } else {
                toCut = end - begin;
            }
            if (allCutTime < toCut) {
                toCut = allCutTime;
            }
            allCutTime = allCutTime - toCut;
        }
    }
    unsigned int remainingDur = LogicTo->getPhase(actStep).duration - getDiffToStartOfPhase(LogicTo, startPos);
    unsigned int newDur = remainingDur - toCut;
    myTo->changeStepAndDuration(myControl,step,actStep,newDur);

    // changes the duration of all other phases
    int currStep = actStep + 1;
    if (currStep == (int) LogicTo->getPhases().size()) {
        currStep = 0;
    }
    while (allCutTime > 0) {
        for (int i=currStep; i<(int) LogicTo->getPhases().size(); i++) {
            size_t beginOfPhase = LogicTo->getOffsetFromIndex(i);
            unsigned int durOfPhase = LogicTo->getPhase(i).duration;
            size_t endOfPhase = beginOfPhase + durOfPhase;
            for (int i=0; i<noBereiche; i++) {
                StretchBereichDef def = getStretchBereichDef(myTo, i+1);
                size_t begin = (size_t) def.begin;
                size_t end = (size_t) def.end;
                if ((beginOfPhase <= begin) && (endOfPhase >= end)) {
                    size_t maxCutOfPhase = end - begin;
                    if (allCutTime< maxCutOfPhase) {
                        maxCutOfPhase = allCutTime;
                    }
                    allCutTime = allCutTime - maxCutOfPhase;
                    durOfPhase = durOfPhase - maxCutOfPhase;
                }
            }
            LogicTo->addOverridingDuration(durOfPhase);
        }
        currStep = 0;
    }
}
void
MSTLLogicControl::WAUTSwitchProcedure_Stretch::adaptLogic(SUMOTime step) {
    SUMOTime gspTo = TIME2STEPS(getGSPValue(*myTo));
    SUMOTime cycleTime = myTo->getDefaultCycleTime();
    // the position, where the logic has to be after synchronisation
    SUMOTime posAfterSyn = myTo->getPhaseIndexAtTime(step);
    // calculate the difference, that has to be equalized
    SUMOTime deltaToCut = 0;
    if (posAfterSyn < gspTo) {
        deltaToCut = posAfterSyn + cycleTime - gspTo;
    } else {
        deltaToCut =  posAfterSyn - gspTo;
    }
    // test, wheter cutting of the Signalplan is possible
    SUMOTime deltaPossible = 0;
    int areasNo = getStretchAreaNo(myTo);
    for (int i = 0; i < areasNo; i++) {
        StretchBereichDef def = getStretchBereichDef(myTo, i + 1);
        assert(def.end >= def.begin);
        deltaPossible += TIME2STEPS(def.end - def.begin);
    }
    int stretchUmlaufAnz = (int) TplConvert::_2SUMOReal(myTo->getParameterValue("StretchUmlaufAnz").c_str());
    deltaPossible = stretchUmlaufAnz * deltaPossible;
    if ((deltaPossible > deltaToCut) && (deltaToCut < (cycleTime / 2))) {
        cutLogic(step, gspTo, deltaToCut);
    } else {
        SUMOTime deltaToStretch = (cycleTime - deltaToCut) % cycleTime;
        stretchLogic(step, gspTo, deltaToStretch);
    }
}
void
MSTLLogicControl::WAUTSwitchProcedure_Stretch::cutLogic(SUMOTime step, SUMOTime startPos, SUMOTime allCutTime) {
    unsigned int actStep = myTo->getIndexFromOffset(startPos);
    // switches to startPos and cuts this phase, if there is a "Bereich"
    int areasNo = getStretchAreaNo(myTo);
    SUMOTime toCut = 0;
    for (int i = 0; i < areasNo; i++) {
        StretchBereichDef def = getStretchBereichDef(myTo, i + 1);
        SUMOTime begin = TIME2STEPS(def.begin);
        unsigned int end = TIME2STEPS(def.end);
        size_t stepOfBegin = myTo->getIndexFromOffset(begin);
        if (stepOfBegin == actStep)	{
            if (begin < startPos) {
                toCut = end - startPos;
            } else {
                toCut = end - begin;
            }
            toCut = MIN2(allCutTime, toCut);
            allCutTime = allCutTime - toCut;
        }
    }
    SUMOTime remainingDur = myTo->getPhase(actStep).duration - getDiffToStartOfPhase(*myTo, startPos);
    SUMOTime newDur = remainingDur - toCut;
    myTo->changeStepAndDuration(myControl, step, actStep, newDur);

    // changes the duration of all other phases
    int currStep = (actStep + 1) % (int)myTo->getPhases().size();
    while (allCutTime > 0) {
        for (int i = currStep; i < (int) myTo->getPhases().size(); i++) {
            SUMOTime beginOfPhase = myTo->getOffsetFromIndex(i);
            SUMOTime durOfPhase = myTo->getPhase(i).duration;
            SUMOTime endOfPhase = beginOfPhase + durOfPhase;
            for (int i = 0; i < areasNo; i++) {
                StretchBereichDef def = getStretchBereichDef(myTo, i + 1);
                SUMOTime begin = TIME2STEPS(def.begin);
                SUMOTime end = TIME2STEPS(def.end);
                if ((beginOfPhase <= begin) && (endOfPhase >= end)) {
                    SUMOTime maxCutOfPhase = MIN2(end - begin, allCutTime);
                    allCutTime = allCutTime - maxCutOfPhase;
                    durOfPhase = durOfPhase - maxCutOfPhase;
                }
            }
            myTo->addOverridingDuration(durOfPhase);
        }
        currStep = 0;
    }
}
void
MSTLLogicControl::WAUTSwitchProcedure_Stretch::adaptLogic(SUMOTime step, SUMOReal position) {
    MSSimpleTrafficLightLogic *LogicTo = (MSSimpleTrafficLightLogic*) myTo;
    size_t cycleTime = LogicTo->getDefaultCycleTime();
    // the position, in which the logic has to be switched
    unsigned int startPos = (unsigned int) position;
    // this is the position, where the Logic have to be after synchronisation
    size_t posAfterSyn = LogicTo->getPhaseIndexAtTime(step);

    // switch the toLogic to the startPosition
    // fehlt!!!!
    // erfolgt in cutLogic und/oder stretchLogic!


    // calculate the difference, that has to be equalized
    size_t deltaToCut = 0;
    if (posAfterSyn < startPos) {
        deltaToCut = posAfterSyn + cycleTime - startPos;
    } else deltaToCut =  posAfterSyn - startPos;
    // test, wheter cutting of the Signalplan is possible
    size_t deltaPossible = 0;
    int noBereiche = getStretchBereicheNo(myTo);
    for (int i=0; i<noBereiche; i++) {
        StretchBereichDef def = getStretchBereichDef(myTo, i+1);
        assert(def.end >= def.begin) ;
        deltaPossible = deltaPossible + (size_t)(def.end - def.begin);
    }
    int stretchUmlaufAnz = (int) TplConvert<char>::_2SUMOReal(LogicTo->getParameterValue("StretchUmlaufAnz").c_str());
    deltaPossible = stretchUmlaufAnz * deltaPossible;
    if ((deltaPossible > deltaToCut)&&(deltaToCut < (cycleTime / 2))) {
        cutLogic(step, startPos, deltaToCut);
    } else {
        size_t deltaToStretch = cycleTime - deltaToCut;
        if (deltaToStretch == cycleTime) {
            deltaToStretch = 0;
        }
        stretchLogic(step, startPos, deltaToStretch);
    }

}
void
MSTLLogicControl::WAUTSwitchProcedure_Stretch::stretchLogic(SUMOTime step, unsigned int startPos, size_t deltaToStretch) {
    MSSimpleTrafficLightLogic *LogicTo = (MSSimpleTrafficLightLogic*) myTo;
    unsigned int currPos = startPos;
    unsigned int currStep = LogicTo->getIndexFromOffset(currPos);
    unsigned int durOfPhase = LogicTo->getPhase(currStep).duration;
    size_t allStretchTime = deltaToStretch;
    size_t remainingStretchTime = allStretchTime;
    int StretchTimeOfPhase = 0;
    size_t stretchUmlaufAnz = (size_t) TplConvert<char>::_2SUMOReal(LogicTo->getParameterValue("StretchUmlaufAnz").c_str());
    SUMOReal facSum = 0;
    int noBereiche = getStretchBereicheNo(myTo);
    int x;
    for (x=0; x<noBereiche; x++) {
        StretchBereichDef def = getStretchBereichDef(myTo, x+1);
        facSum += def.fac;
    }
    facSum *= stretchUmlaufAnz;


    //switch to startPos and stretch this phase, if there is a end of "bereich" between startpos and end of phase
    size_t diffToStart = getDiffToStartOfPhase(LogicTo, currPos);
    for (x=0; x<noBereiche; x++) {
        StretchBereichDef def = getStretchBereichDef(myTo, x+1);
        size_t end = (size_t) def.end;
        size_t endOfPhase = (size_t)(currPos + durOfPhase - diffToStart);
        if (end <= endOfPhase && end >= currPos) {
            SUMOReal fac = def.fac;
            SUMOReal actualfac = fac / facSum;
            facSum = facSum - fac;
            StretchTimeOfPhase = (int)((float)remainingStretchTime * actualfac + 0.5);
            remainingStretchTime = allStretchTime - StretchTimeOfPhase;
        }
    }
    durOfPhase = durOfPhase - diffToStart + StretchTimeOfPhase;
    myTo->changeStepAndDuration(myControl,step,currStep,durOfPhase);

    currStep ++;
    if (currStep >= LogicTo->getPhases().size()) {
        currStep = 0;
    }

    // stretch all other phases, if there is a "bereich"
    while (remainingStretchTime > 0) {
        for (unsigned int i=currStep; i<LogicTo->getPhases().size() && remainingStretchTime > 0; i++) {
            durOfPhase = LogicTo->getPhase(i).duration;
            size_t beginOfPhase = LogicTo->getOffsetFromIndex(i);
            size_t endOfPhase = beginOfPhase + durOfPhase;
            for (int j=0; j<noBereiche && remainingStretchTime > 0; j++) {
                StretchBereichDef def = getStretchBereichDef(myTo, j+1);
                size_t end = (size_t) def.end;
                SUMOReal fac = def.fac;
                if ((beginOfPhase <= end) && (endOfPhase >= end)) {
                    SUMOReal actualfac = fac / facSum;
                    StretchTimeOfPhase = (int)((float)remainingStretchTime * actualfac + 0.5) ;
                    facSum -= fac;
                    durOfPhase += StretchTimeOfPhase;
                    remainingStretchTime -= StretchTimeOfPhase;
                }
            }
            LogicTo->addOverridingDuration(durOfPhase);
        }
        currStep = 0;
    }
}