//
//  presetManager.mm
//  oscSenderExample
//
//  Created by Robert Tubb on 07/11/2012.
//
//

#include "presetManager.h"

//---------------------------------------------------------------------------
extern Grid theGridView;
PresetManager presetManager;
extern EventLogger eventLogger;
extern PresetAlertViewController *presetAlertViewController;
//---------------------------------------------------------------------------
vector<ofColor> Preset::makePresetPicture(TwoVector coord){
    // convert midi parameters to a nice piccy
    vector<int> params = theGridView.calculateParamsFromCoord(coord);
    vector<ofColor> pixCols;
    
    ofColor col(255,0,0);
    for(int i=0; i<9;i++){
        col.setHue(params[i]*2);
        pixCols.push_back(col);
    }
    return pixCols;
}
//---------------------------------------------------------------------------
void Preset::draw(){
    // TODO bit stupid actually. make it a shaded ball / dot 
    
    int sz = 2;
    TwoVector pos = theGridView.coordToPixel(coordinates); // euch -rely on grid view?
    
    if(pixVals.size() < 9){
        cout << "NO PRESET PIC\n";
        return;
    }
    //middle row
    // centre
    ofSetColor(pixVals[0]);
    ofRect(pos.x, pos.y,sz,sz);
    // right
    ofSetColor(pixVals[1]);
    ofRect(pos.x+sz, pos.y,sz,sz);
    // left
    ofSetColor(pixVals[2]);
    ofRect(pos.x-sz, pos.y,sz,sz);
    
    //top
    // centre
    ofSetColor(pixVals[3]);
    ofRect(pos.x, pos.y+sz,sz,sz);
    // right
    ofSetColor(pixVals[4]);
    ofRect(pos.x+sz, pos.y+sz,sz,sz);
    // left
    ofSetColor(pixVals[5]);
    ofRect(pos.x-sz, pos.y+sz,sz,sz);
    
    // bottom
    // centre
    ofSetColor(pixVals[6]);
    ofRect(pos.x, pos.y-sz,sz,sz);
    // right
    ofSetColor(pixVals[7]);
    ofRect(pos.x+sz, pos.y-sz,sz,sz);
    // left
    ofSetColor(pixVals[8]);
    ofRect(pos.x-sz, pos.y-sz,sz,sz);
};
//---------------------------------------------------------------------------
Json::Value Preset::presetToJson(){
    // create the string for this instance of Preset object
    
    Json::Value presetVal;
    
    presetVal["creatorUserName"] = creatorUserName;
    presetVal["creatorDeviceID"] = creatorDeviceID;
    presetVal["creationTime"] =     creationTime;
    presetVal["name"] =             name;
    presetVal["coordinates"]["x"] = coordinates.x;
    presetVal["coordinates"]["y"] = coordinates.y;
    
    
    return presetVal;
}
//---------------------------------------------------------------------------
PresetManager::PresetManager(){
    timesOpened = 0;
    nextID = 0;
   
    string ts = ofGetTimestampString();
    
    presetAlertShowing = false;

    
    cout << "ofGetTimestampString: " << ts << '\n';
}
//---------------------------------------------------------------------------
Json::Value PresetManager::allPresetsToJson(){
    Json::Value root;
 
    // use jsoncpp
    vector<Preset *>::iterator presetIter;
    
    int i = 0;
    for(presetIter = thePresets.begin(); presetIter < thePresets.end(); presetIter++){
        root["presets"][i] = (*presetIter)->presetToJson();
        i++;
    }
    
    return root;
}
//---------------------------------------------------------------------------
void PresetManager::readJsonToPresets(const string &jsonFile){
    Json::Value root;
    Json::Reader reader;

    
    ifstream theFile(jsonFile.c_str());
    stringstream fileText;
    string line;
    if(!theFile){
        cout<<"can't find preset file \n";
        return;
    }else{
        
        while(theFile){
            theFile >> line;
            // cout << line << "\n"; // lots?
            fileText << line;
            
        }
        
        theFile.close();
    }
    
    bool parsingSuccessful = reader.parse( fileText.str(), root );

    if ( !parsingSuccessful )
    {
        // report to the user the failure and their locations in the document.
        std::cout  << "Failed to parse preset JSON: \n"
        << reader.getFormattedErrorMessages();
        return;
    }

    // now put into variables
    const Json::Value jpresets = root["presets"];
    
    for ( int index = 0; index < jpresets.size(); ++index ) thePresets.push_back(new Preset(jpresets[index]));
    
    //printAll();
     
}
//---------------------------------------------------------------------------
void PresetManager::printAll(){
    cout << "ALL PRESETS: \n";
    vector<Preset *>::iterator presetIter;
    for(presetIter = thePresets.begin(); presetIter < thePresets.end(); presetIter++){
        cout << **presetIter;
        
    }
}
//---------------------------------------------------------------------------
void PresetManager::showNameDialog(){
    if(!presetAlertShowing){ // this is to stop wierd infinite loop in ios5 (simulator)
        presetAlertShowing = true;
        [presetAlertViewController showPresetNamePrompt];
        
    }
    
}
//---------------------------------------------------------------------------
// when save button pressed
int PresetManager::addPreset(const string name){

    presetAlertShowing = false;
    // check for same name
    vector<Preset *>::iterator iter;
    for(iter = thePresets.begin(); iter < thePresets.end(); iter++){
        if ((*iter)->name == name){
            cout << " Preset by that name exists\n";
            
            // use exceptions!
            return -1;
        }
    }
    if(name == ""){
        cout << "Please name preset\n";
        return -2;
        
    }
    // yuk shouldn't have to know about eventlogger and grid view...
    thePresets.push_back(new Preset(theGridView.getCoord(), name,nextID, eventLogger.userName, eventLogger.deviceID));
    
    // poke grid view to get it to show details
    theGridView.snapCheck();
    // if ok
    return nextID++;
}

//---------------------------------------------------------------------------

int PresetManager::loadPreset(const TwoVector coord, const string name, long long stime){
    thePresets.push_back(new Preset(coord, name,nextID, stime));
   
     // if ok
    return nextID++;
}
//---------------------------------------------------------------------------
vector<Preset *> PresetManager::getPresetsInRange(const TwoVector min, const TwoVector max){
    //return all the coordinates. oh and names (displayed at certain scales?).
    
    // TODO INEFFICIENT FOR LOTS OF PRESETS. CALLED EVERY GRAPHICS UPDATE!
    // so: put burden on saving rather than retrieving, make into list and index using coordinates
    
    vector<Preset *> results;
    vector<Preset *>::iterator presetIter;
    for(presetIter = thePresets.begin(); presetIter < thePresets.end(); presetIter++){
        if( ((*presetIter)->coordinates.x > min.x ) && ((*presetIter)->coordinates.y > min.y ) && ((*presetIter)->coordinates.x < max.x ) && ((*presetIter)->coordinates.y < max.y )){
            results.push_back(*presetIter);
        }

    }
    return results;
    
}


//---------------------------------------------------------------------------
void PresetManager::drawPresetsInRange(const TwoVector min, const TwoVector max){
    vector<Preset *> pInRange = getPresetsInRange(min, max);
    vector<Preset *>::iterator piter;
    int i = 0;
    for(piter = pInRange.begin(); piter < pInRange.end(); piter++){

        (*piter)->draw();
        i++;
    }
 
}
//----------------------------------------------cu-----------------------------
void PresetManager::startupLoadAll(){
    // get stuff from file
    // load file

    string fname = ofxiPhoneGetDocumentsDirectory() + PRESET_FILENAME;
    
    readJsonToPresets(fname);
    
    timesOpened++;
}

//---------------------------------------------------------------------------
void PresetManager::exitAndSaveAll(){
    ofFile presetFile(ofxiPhoneGetDocumentsDirectory() +PRESET_FILENAME,ofFile::WriteOnly);
    
    // stick all the stuff in a json value
    Json::Value root = allPresetsToJson();
    
    cout << root;
    presetFile << root;
     
    
}

//---------------------------------------------------------------------------
void PresetManager::clearAll(){
    thePresets.clear();
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------