/* 
 * File:   VideoRegions.cpp
 * Author: carlos
 * 
 * Created on 6 de noviembre de 2012, 15:47
 */

#include "VideoRegions.h"
#include <fstream>


VideoRegions::VideoRegions() { 
    m_videoRegions.clear();
    this->m_frameNum = 0;
}

VideoRegions::VideoRegions(const VideoRegions& orig) {
    this->m_dataPath = orig.m_dataPath;
    this->m_frameNum = orig.m_frameNum;
    this->m_fileLength = orig.m_fileLength;
    this->m_videoRegions = orig.m_videoRegions;
}

VideoRegions::~VideoRegions() {
}

int VideoRegions::copy(int idxOrigin, int idxDestiny){
    m_videoRegions.at(idxDestiny) = m_videoRegions.at(idxOrigin);
    return 0;
}

int VideoRegions::saveMarkedData(){
    int ret = 0;
    
    printf("saving: %s\n",m_dataPath.data());
    try{
        ofstream ofs(m_dataPath.data(), ios::binary | ios::trunc | ios::out);
        boost::archive::binary_oarchive oa(ofs);
        oa << m_videoRegions;
        oa << m_frameNum;
    }
    catch(boost::archive::archive_exception exc){
        printf("error saving\n");
        ret = -1;
    }
    
    return ret;
}

int VideoRegions::loadMarkedData(){
    int ret = 0;
    
    printf("loading: %s\n",m_dataPath.data());
    try{
        m_videoRegions.clear();
        ifstream ifs(m_dataPath.data(), ios::binary | ios::in);
        boost::archive::binary_iarchive ia(ifs);
        ia >> m_videoRegions;
        ia >> m_frameNum;
    }
    catch(boost::archive::archive_exception exc){
        printf("error loading\n");
        ret = -1;
    }    
    
    return ret;
}

int VideoRegions::openFile(string dataFile, int maxSize){

    m_dataPath = dataFile;    
    m_fileLength = maxSize;
           
    if (this->loadMarkedData() != 0){
        for (int i=0; i<m_fileLength; i++){
            ImgRegion newRegion = ImgRegion(string("road"));          
            FrameRegions_t oneFrame; 
            oneFrame.clear();
            oneFrame.push_back(newRegion);
            m_videoRegions.push_back(oneFrame);
        }
        this->m_frameNum = 0;
        printf("Structure of %d elements created\n",m_fileLength);
    }
    
    return 0;
}

int VideoRegions::addPoint(int nFrame, int nLabel, int x, int y){
    this->printLabelAndPts(nFrame);
    printf("label %d addPoint %d , %d\n",nLabel,x,y);
    m_videoRegions.at(nFrame).at(nLabel).addPoint(x,y);    
    this->printLabelAndPts(nFrame);
    return 0;
}

int VideoRegions::clearPts(int nFrame, int nLabel){
    m_videoRegions.at(nFrame).at(nLabel).clearPoints();
    return 0;
}

int VideoRegions::setPoint(int nFrame, int nLabel, int nPt, Pt_t value){
    m_videoRegions.at(nFrame).at(nLabel).setPoint(nPt,value);
    return 0;
}

Pt_t VideoRegions::getPoint(int nFrame, int nLabel, int nPt){
    return m_videoRegions.at(nFrame).at(nLabel).getPoint(nPt);    
}

int VideoRegions::getNumPts(int nFrame, int nLabel){
    return m_videoRegions.at(nFrame).at(nLabel).getNumPoints();
}

int VideoRegions::getNumLabels(int nFrame){
    return m_videoRegions.at(nFrame).size();
}

int VideoRegions::nearestPointIndex(int nFrame, int x, int y, int* nRegion, int* nPt){
    int nearestPt = -1;
    int nearestRegion = -1;
    double minDist = 99999;

    FrameRegions_t regions = m_videoRegions.at(nFrame);
    for (int i=0; i<regions.size(); i++){
        ImgRegion region = regions.at(i);
        for (int j=0; j<region.getNumPoints(); j++){
            double dist = ImgRegion::euclideanDistance(x,y,
                    region.getPoint(j).GetX(),region.getPoint(j).GetY());
            if (dist < minDist){
                minDist = dist;
                nearestRegion = i;
                nearestPt = j;
            }
        }
    }
    *nRegion = nearestRegion;
    *nPt = nearestPt;
    
    return 0;
}

int VideoRegions::printLabelAndPts(int nFrame){
    printf("------------------\n");
    for (int nLabel=0; nLabel<m_videoRegions.at(nFrame).size(); nLabel++){
        printf("frame(%d)region(%s):",
                nFrame,
                m_videoRegions.at(nFrame).at(nLabel).getLabel().data());
        for (int nPt=0; nPt<m_videoRegions.at(nFrame).at(nLabel).getNumPoints(); nPt++){
            printf("(%d,%d)",
                    m_videoRegions.at(nFrame).at(nLabel).getPoint(nPt).GetX(),
                    m_videoRegions.at(nFrame).at(nLabel).getPoint(nPt).GetY());
        }
        printf("\n");
    }
    return 0;
}

int VideoRegions::addLabel(int nFrame, string labelName){
    ImgRegion newObj = ImgRegion(labelName);    
    m_videoRegions.at(nFrame).push_back(newObj);
    return 0;
}

int VideoRegions::removeLabel(int nFrame, int nLabel){
    int numLabels = m_videoRegions.at(nFrame).size();
    FrameRegions_t aux;
    for (int i=0; i<numLabels; i++){
        if (i != nLabel)
            aux.push_back(m_videoRegions.at(nFrame).at(i));
    }
    m_videoRegions.at(nFrame) = aux;
    return 0;
}