/* This file is part of the source code for the following publication:
 * Assembling Self-Supporting Structures, Deuss et al., SIGGRAPH Asia 2014
 *
 * Copyright (C) 2014 Mario Deuss <mario.deuss@epfl.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef EQUILIBRIUMFORCES_H
#define EQUILIBRIUMFORCES_H

#include "SelfAssemblyDefines.h"
#include "Sequence.h"
#include "Statistics.h"

namespace SelfAssembly{
class Assembly;

class EquilibriumForces
{

public:
	typedef Eigen::Vector3d Force;
	typedef Eigen::MatrixX3d Forces;
	typedef Eigen::VectorXd Magnitudes;
public:
	EquilibriumForces( const Assembly* _a ):upd_(false){ reset(_a); }
	
	void reset( const Assembly* _a );
	void fillNan();
	const Assembly* a() const { return a_;}
	
	void setForceInIfsBasis(Idx ifsi, Idx vi , const Force &f);
	Force forceInIfsBasis(Idx ifsi, Idx vi ) const;
	Force force(Idx ifsi, Idx vi, bool scaled=false ) const;
	bool isActiveF(Idx ifsi, Idx vi) const;

	double archity(Idx ifsi) const{ return maxFDotN(ifsi); }
	double cone(Idx ifsi) const;
	double maxF(Idx ifsi) const;
	double maxFDotN(Idx ifsi) const;
	bool isActiveI(Idx ifsi) const;

	void setChainForceMagnitude(Idx ci, double c );
	double chainForceMagnitude(Idx ci , bool scaled=false) const;
	//false in case ci is not active
	bool isActiveC(Idx ci) const;
	double chainLpPowerP( double p );

	//Counts the number of changes in chains w.r.t to LastEqf. first return is newly introduced chains, second is removed chains
	std::pair<unsigned int, unsigned int> chainChange(const EquilibriumForces& eqf );

	void computeStatistics();
	const Statistics& forceStatistics() const { assert(upd_); return fS_;}
	const Statistics& chainStatistics() const { assert(upd_); return cS_;}
	const Statistics& intfsStatistics() const { assert(upd_); return iS_;}
	const Statistics& anchorStatistics()const { assert(upd_); return aS_;}

	void state( Idx bi, State& s ) const;
	double anchorScalarSum(Idx ai) const;

private:
	Forces FInBasis_;
	Magnitudes chainFMag_;
	const Assembly* a_;

	bool upd_;
	Statistics fS_;
	Statistics cS_;
	Statistics iS_;
	Statistics aS_;
};

}
#endif // EQUILIBRIUMFORCES_H
