#include "AdvPeakData.hh"

AdvPeakData::AdvPeakData() {
    this->peakList.clear();
};

AdvPeakData::AdvPeakData(const AdvPeakData &pc) {
    this->peakList=vector<AdvPeak>(pc.peakList.begin(), pc.peakList.end());
}

AdvPeakData::~AdvPeakData() {
    this->peakList.clear();
};

AdvPeakData AdvPeakData::operator = (const AdvPeakData &pc) {
    this->peakList.assign(pc.peakList.begin(), pc.peakList.end());
    return *this;
}

void AdvPeakData::add(AdvPeak peak) {

    this->peakList.push_back(peak);
};

void AdvPeakData::add(const AdvPeakType type, const Double x, const Double h, const Double w, const Double xl, const Double xu) {
    this->peakList.push_back(*(new AdvPeak(type, x, h, w, xl, xu)));
};


void AdvPeakData::clear() {
    this->peakList.clear();
};

void AdvPeakData::erase(const UInt4 i) {

    if ( ! this->peakList.empty() ) {
        if ( 0 <= i && i < this->peakList.size() ) {
            std::vector<AdvPeak>::iterator itr;
            UInt4 ct;
            for (ct=0, itr=this->peakList.begin(); ct<=i; ++ct, ++itr) { ; }
            this->peakList.erase(itr);
        }
    }
};

vector<Double> AdvPeakData::toVector() {

    vector<Double> *retval = new vector<Double>();
    vector<Double> v;

    for (std::vector<AdvPeak>::iterator itr=this->peakList.begin(); itr != this->peakList.end(); ++itr) {
        v = itr->toVector();
        retval->insert(retval->end(), v.begin(), v.end());
    }

    return *retval;
};

PyObject *AdvPeakData::toPyList() {
    CppToPython *cp = new CppToPython();
    PyObject *r = cp->VectorDoubleToList( this->toVector() );
    delete cp;
    return r;
}


Double * AdvPeakData::toArray() {

    if ( this->peakList.empty() ) {
        return static_cast<Double*>(NULL);
    }

    Double *retval = new Double[sizeOfArray()];
    vector<Double> v;
    UInt4 ct;

    ct=0;
    for (std::vector<AdvPeak>::iterator i=this->peakList.begin(); i != this->peakList.end(); ++i) {
        v = i->toVector();
        for (UInt4 j=0; j<v.size(); ++j) {
            retval[ct]=v.at(j);
            ++ct;
        }
    }
    return retval;
}

UInt4 AdvPeakData::sizeOfArray() {
    return this->peakList.size()*AdvPeak::shortSize;
}

vector<Double> AdvPeakData::toFullVector() {

    vector<Double> *retval = new vector<Double>();
    vector<Double> v;

    for (std::vector<AdvPeak>::iterator itr=this->peakList.begin(); itr != this->peakList.end(); ++itr) {
        v = itr->toFullVector();
        retval->insert(retval->end(), v.begin(), v.end());
    }

    return *retval;
};

Double * AdvPeakData::toFullArray() {

    if ( this->peakList.empty() ) {
        return static_cast<Double*>(NULL);
    }

    Double *retval = new Double[sizeOfFullArray()];
    vector<Double> v;
    UInt4 ct;

    ct=0;
    for (std::vector<AdvPeak>::iterator i=this->peakList.begin(); i != this->peakList.end(); ++i) {
        v = i->toFullVector();
        for (UInt4 j=0; j<v.size(); ++j) {
            retval[ct]=v.at(j);
            ++ct;
        }
    }
    return retval;
}

UInt4 AdvPeakData::sizeOfFullArray() {
    return this->peakList.size()*AdvPeak::fullSize;
}

gsl_vector * AdvPeakData::toGslVector() {

    if ( this->peakList.empty() ) {
        return static_cast<gsl_vector*>(NULL);
    }

    gsl_vector *retval = gsl_vector_alloc(this->peakList.size() * AdvPeak::shortSize);
    vector<Double> v;
    UInt4 ct=0;
    for (std::vector<AdvPeak>::iterator i=this->peakList.begin(); i != this->peakList.end(); ++i) {
        v = i->toVector();
        for (UInt4 j=0; j<v.size(); ++j) {
            gsl_vector_set(retval, ct, v.at(j));
            ++ct;
            //std::cerr << "ct=" << ct << endl;
        }
    }
    return retval;
}

gsl_vector * AdvPeakData::toFullGslVector() {

    if ( this->peakList.empty() ) {
        return static_cast<gsl_vector*>(NULL);
    }

    gsl_vector *retval = gsl_vector_alloc(this->peakList.size() * AdvPeak::fullSize);
    vector<Double> v;
    UInt4 ct=0;
    for (std::vector<AdvPeak>::iterator i=this->peakList.begin(); i != this->peakList.end(); ++i) {
        v = i->toFullVector();
        for (UInt4 j=0; j<v.size(); ++j) {
            gsl_vector_set(retval, ct, v.at(j));
            ++ct;
        }
    }
    return retval;
}

void AdvPeakData::Dump() {

    std::cout << "a list of peaks (type: ";
    std::cout << PEAK.symbol.c_str() << " -> peak";
    std::cout << ", ";
    std::cout << SHOLDER_I.symbol.c_str() << " -> sholder in increase region";
    std::cout << ", ";
    std::cout << SHOLDER_D.symbol.c_str() << " -> sholder in decrease region";
    std::cout << endl;

    std::cout << setw(5) << "No."; AdvPeak::title(stdout); // table header
    UInt4 ct=0;
    for (std::vector<AdvPeak>::iterator p = this->peakList.begin(); p != this->peakList.end(); ++p) {
        std::cout << setw(5) << ct; p->dump(stdout);
    }
    std::cout << endl;

    //fprintf(stdout, "a list of peaks (type: %s -> peak, %s -> sholder in increase region, %s -> sholder in decrease region)\n",
    //        PEAK.symbol.c_str(), SHOLDER_I.symbol.c_str(), SHOLDER_D.symbol.c_str()
    //);
    //fprintf(stdout, "%5s ", "No.");
    //Peak::title(stdout);

    //std::vector<AdvPeak>::iterator i;
    //UInt4 ct;
    //for ( i=this->peakList.begin(), ct=0; i != this->peakList.end(); ++i, ++ct) {
    //    fprintf(stdout, "%5u ", ct);
    //    i->dump(stdout);
    //}
    //fprintf(stdout, "\n");
};

UInt4 AdvPeakData::size() const {
    return this->peakList.size();
}

AdvPeak AdvPeakData::getPeak(const UInt4 i) const {
    return this->peakList.at(i);
}
