#include "initial_state.hpp"

Tank::Tank(){
  saturation=0.8;
  left=0.4;right=0.6;
  bottom=0.6;top=0.7;
  delta_left=0.05;
  delta_right=0.05;
  delta_bottom=0.05;
  delta_top=0.05;
}




InitialState::InitialState(){
  hsat=nullptr;
  Pinit=nullptr;
}

void
InitialState::update(Geometry& _geometry,Spline& _Ssat){
  Ssat=&_Ssat;
  geometry=&_geometry;
  if(hsat!=nullptr){
    delete[] hsat;
    for(size_t i=0;i<geometry->nX;++i){
      delete[] Pinit[i];
    }
    delete[] Pinit;
  }
  hsat=new double[geometry->nX];
  Pinit=new double*[geometry->nX];

  for(size_t i=0;i<geometry->nX;++i){
    size_t nZ=geometry->nZ[i];
    Pinit[i]=new double[nZ];
  }
  updatePressure();
}
Tank*
InitialState::addTank(){
  Tank* tank=new Tank;
  tanks.push_back(tank);
  return tank;
  updatePressure();
}

void
InitialState::removeTank(Tank* tank){
  for(auto it=tanks.begin();it!=tanks.end();++it){
    if(*it==tank){
      delete *it;
      tanks.erase(it);
      return;
    }
  }
  updatePressure();
}


InitialState::~InitialState(){
  if(hsat!=nullptr){
    delete[] hsat;
    for(size_t i=0;i<geometry->nX;++i){
      delete[] Pinit[i];
    }
    delete[] Pinit;
  }
  for(auto it=tanks.begin();it!=tanks.end();++it){
    delete(*it);
  }
}

void
InitialState::updatePressure(){

  for(size_t i=0;i<geometry->nX;++i){
    double x=double(i)/(geometry->nX-1);
    hsat[i]=(*Ssat)(x)*geometry->factor;
    size_t nZ=geometry->nZ[i];
    double temp=hsat[i]+Physics::model_data[0]/(Physics::g*Physics::rho); //TODO : replace Physics::model_data[0] by Psat in future
    for(size_t j=0;j<nZ;++j){
      double z=geometry->Z[i][j];
      Pinit[i][j]=Physics::rho*Physics::g*(temp-z);
      for(auto it=tanks.begin();it!=tanks.end();++it){
        Tank* tank=*it;
        double S=tank->saturation;
        double l=tank->left;
        double r=tank->right;
        double t=tank->top;
        double b=tank->bottom;
        double dl=tank->delta_left;
        double dr=tank->delta_right;
        double dt=tank->delta_top;
        double db=tank->delta_bottom;

        double Ps=Physics::s_inv(S);
      cout<<S<<" "<<Ps<<endl;
      double Px,Pz;
      double zn=z/geometry->factor;
      if(x<=l){
        Px=(Ps-Physics::Psec)*(x-l)/dl+Ps;
      }
      else if(x>=r){
        Px=(Physics::Psec-Ps)*(x-r)/dr+Ps;
      }
      else{
        Px=Ps;
      }
      if(zn<=b){
        Pz=(Ps-Physics::Psec)*(zn-b)/db+Ps;
      }
      else if(zn>=t){
        Pz=(Physics::Psec-Ps)*(zn-t)/dt+Ps;
      }
      else{
        Pz=Ps;
      }
      Pinit[i][j]=max(max(min(Px,Pz),Pinit[i][j]),Physics::Psec);
    }



      //TODO : voir considrer max avec psec
    }
  }
}
