#include "couche.h"

Couche::Couche(){
    nbrNeurone=0;
    nextCouche=NULL;
    listNeurone=NULL;
    synSortantes = SynapseMatrix();
}

Couche::~Couche(){
    deleteList();
}

Couche::Couche(const unsigned int nbr,const Couche* next){
    nbrNeurone=(unsigned int)nbr;
    if(next!=NULL){
        setNextCouche(next);
    }
    else{
        nextCouche = NULL;
        synSortantes = SynapseMatrix();
    }
    listNeurone=NULL;
    for(unsigned int i=0;i<nbr;++i)
        listNeurone=new Neurone(0.0,listNeurone);
}

const unsigned int Couche::getNumber() const{
    return nbrNeurone;
}

Neurone& Couche::operator[](const unsigned int i) const throw(const unsigned int){
    if(i>(getNumber()-1))
        throw(i);
    Neurone* res=listNeurone;
    for(unsigned int j=0;j<i;++j)
        res=res->getNextNeurone();
    return *res;
}

bool Couche::operator==(const Couche c){
    return ((this)==(&c));
}

Couche& Couche::operator=(const Couche& c){
    if(this!=&c){
        nbrNeurone=c.getNumber();
        nextCouche=c.getNextCouche();
        deleteList();
        listNeurone=copy(c.listNeurone);
        synSortantes=c.synSortantes;
    }
    return *this;
}

void Couche::setNextCouche(const Couche* c) throw(std::string){
    //cout << "setnextcouche : " << this << " -> " << c << endl;
    if(c==NULL){
        throw(std::string("Passing NULL as next couche forbiden"));
    }
    else{
        nextCouche=(Couche*)c;
        synSortantes = SynapseMatrix(getNumber(),c->getNumber());
        synSortantes.randomize();
    }
}

void Couche::randomizeSynapseMatrix(){
    synSortantes.randomize();
}

Couche* Couche::getNextCouche() const{
    return nextCouche;
}

void Couche::deleteN(Neurone* n){
    if(n){
        deleteN(n->getNextNeurone());
        delete n;
        n=NULL;
    }
}

void Couche::deleteList(){
    deleteN(listNeurone);
}

Neurone* Couche::copy(Neurone* n){
    if(n){
        return new Neurone(n->getWeight(),copy(n->getNextNeurone()));
    }
    return NULL;
}

Synapse& Couche::getSynapse(const unsigned int neurThisCouche,const unsigned int neurNextCouche) const throw(const unsigned int,std::string){
    return synSortantes(neurThisCouche,neurNextCouche);
}

ostream & operator<<(ostream& os,const Couche & c){
    unsigned int size = c.getNumber();
    for(unsigned int i=0 ; i<size ; i++)
        os << setw(6) << c[i].getWeight() << " ";
    os << endl;
    return os;
}

void Couche::printSynapseMatrix(){
    cout << synSortantes;
    }
