//
//  SequenceGenerator.mm
//  riftathon
//
//  Created by Robert Tubb on 21/10/2014.
//
//

#include "SequenceController.h"

Step::Step(){
    type = COUNT_IN;
    
    showsTargetIcon = false;
    showsControlSettings = false;
    showsControlGuides = false;
    showsMatchResults = false;
    isPreview = false;
    
    allowsCandidateControl = false;
    playsTarget = false;
    playsCandidate = false;
    
    playsMetroClick = true;
    
    isLastOfSeq = false;
    isLastOfRun = false;
    isLastOfAll = false;
    presetIndex = -1;
    seqNumber = -1;
    runNumber = -1;
    
    tempo = MIN_TEMPO;
}

void Step::setAsPreviewShower(){
    type = PREVIEW_DISPLAY;
    showsTargetIcon = true;
    showsControlSettings = true;
    showsControlGuides = true;
    showsMatchResults = false;
    isPreview = true;
    
    allowsCandidateControl = false;
    playsTarget = true;
    playsCandidate = false;
    playsMetroClick = false;
}
void Step::setAsPreviewPlayer(){
    type = PREVIEW_PLAY;
    showsTargetIcon = true;
    showsControlSettings = true;
    showsControlGuides = true;
    showsMatchResults = false;
    isPreview = true;
    
    allowsCandidateControl = false;
    playsTarget = true;
    playsCandidate = false;
    
    playsMetroClick = false;
}
void Step::setAsMatchingPreparer(){
    type = MATCHING_INTERACTION;
    showsTargetIcon = true;
    showsControlSettings = false;
    showsControlGuides = true;
    showsMatchResults = false;
    isPreview = false;
    
    allowsCandidateControl = true;
    playsTarget = false;
    playsCandidate = false;
    
    playsMetroClick = false;
}
void Step::setAsMatchingReckoner(){
    type = MATCHING_RESULT;
    showsTargetIcon = true;
    showsControlSettings = false;
    showsControlGuides = true;
    showsMatchResults = true; // shows how far off you were?
    isPreview = false;
    
    allowsCandidateControl = false;
    playsTarget = false;
    playsCandidate = true;
    
    playsMetroClick = false;
}


//=================================================================
//=================================================================
//=================================================================

SequenceController::SequenceController(){
    tempoInc = float(MAX_TEMPO - MIN_TEMPO) / float(NUM_TEMPO_STEPS);
    generateSteps();
    setToStart();
};
Step SequenceController::getNextStep(){
    
    currentStep++;
    if ((*currentStep).isLastOfRun){
        // uh
    }
    if ((*currentStep).isLastOfSeq){
        
    }
    return (*currentStep);
    
};
void SequenceController::setToStart(){
    currentStep = steps.begin();
}
void SequenceController::stepForward(){
    currentStep++;
};
float SequenceController::getStartTickTime(){
    return 1000. * (60.0/MIN_TEMPO);
}

void SequenceController::generateSteps(){
    srand (time(NULL));
    
    int run = 0;
    
    
    
    for(int numInSequence = MIN_TARGETS_IN_SEQUENCE; numInSequence <= MAX_TARGETS_IN_SEQUENCE; numInSequence++){
        generateCountIn(2);
        generateARun(run, numInSequence);
        
        steps.back().isLastOfRun = true;
        run++;
        cout << "-generate run finished-" << endl;
    }
    steps.back().isLastOfAll = true;
};
void SequenceController::generateCountIn(int countInLength){
    Step countStep;
    for (int i = 0; i < countInLength; i++){
        countStep.numInSequence = countInLength - i + 1;
        steps.push_back(countStep);
        
    }
};
void SequenceController::generateARun(int run, int numInSequence){
    float curTempo = MIN_TEMPO;
    int seqNo = 0;
    
    for(int tempoLevel = 0; tempoLevel < NUM_TEMPO_STEPS; tempoLevel++){
        
        vector<int> stepPreset;
        
        // get some random ints
        for(int n=0; n < numInSequence; n++){
            int nextPreset = getRandomButNot(NUM_PRESETS,stepPreset);
            stepPreset.push_back(nextPreset);
            cout << nextPreset << ",";
        }
        // put preview
        Step nextStep;
        
        int n = 0;
        for(auto si = stepPreset.begin(); si < stepPreset.end(); si++){
            // put loader
            
            nextStep.presetIndex = *si;
            nextStep.runNumber = run;
            nextStep.seqNumber = seqNo;
            nextStep.numInSequence = n;
            nextStep.tempo = curTempo;
            nextStep.setAsPreviewShower();
            steps.push_back(nextStep);
            
            // put player
            //
            nextStep.setAsPreviewPlayer();
            steps.push_back(nextStep);
            n++;
        }
        // last one in sequence allows control ?
        steps.back().allowsCandidateControl = true;
        // put in matching sequence
        n = 0;
        for(auto si = stepPreset.begin(); si < stepPreset.end(); si++){
            // put loader
            
            nextStep.presetIndex = *si;
            nextStep.numInSequence = n;
            nextStep.setAsMatchingPreparer();
            steps.push_back(nextStep);
            
            // put player
            
            nextStep.setAsMatchingReckoner();
            steps.push_back(nextStep);
            n++;
        }
        
        steps.back().isLastOfSeq = true;
        curTempo += tempoInc;
        seqNo++;
        cout << endl;
        
    }
    
}


int SequenceController::getRandomButNot(int max, vector<int> notThese){
    
    bool there = true;
    int randomInt = rand() % max;
    
    if (notThese.size()){
        while(there){
            randomInt = rand() % max;
            vector<int>::iterator result = std::find(notThese.begin(), notThese.end(), randomInt);
            there =  (result != notThese.end());
        }
    }
    return randomInt;
    
};