/*
 * Copyright (C) 2008-2012 Delft University of Technology - All rights reserved.
 *
 * Author: Reijer Idema
 */

/**
 * @file PowerFlower.h
 * PowerFlower class header.
 */
#ifndef PowerFlower_PowerFlower_h
#define PowerFlower_PowerFlower_h

#include <string>						// HASA string
#include <list>							// HASA list
#include "../PetscUtils/PetscUtils.h"	// HASA PetscErrorCode
#include "LogEvents.h"					// HASA LogEvents (not owned)
#include "PowerSystemExt.h"				// HASA PowerSystemExt
#include "../NonLinearSolver/NonLinearSolver.def"
#include "PowerFlower.def"

// FORWARD DECLARATIONS OUTSIDE POWER FLOWER NAMESPACE
NONLINEARSOLVER_NAMESPACE_BEGIN
class NonLinearSolver;
class Preconditioner;
class ForcingTerms;
NONLINEARSOLVER_NAMESPACE_END

POWERFLOWER_NAMESPACE_BEGIN

// FORWARD DECLARATIONS INSIDE POWER FLOWER NAMESPACE
class PowerFlowProblem;
struct SolveResult;

/**
 * PowerFlower class.
 * Implements the PowerFlower framework.
 */
class PowerFlower
{
public:
	// INITIALIZE/FINALIZE (STATIC)
	/**
	 * Initializes the PowerFlower framework.
	 * The framework should be initialized before creating any PowerFlower objects.
	 * Once initialized the framework can not be re-initialized.
	 * @param argc number of program arguments.
	 * @param ppArgv program arguments.
	 * @param pHelp program help message.
	 * @return \c true on success, \c false on failure.
	 */
	static bool Initialize(int argc, char** ppArgv, char* pHelp);

	/**
	 * Checks if the PowerFlower framework has been initialized.
	 * @return \c true if initialized, \c false if not.
	 */
	static bool IsInitialized(void);

	/**
	 * Finalizes the PowerFlower framework.
	 * The framework should be finalized after all operations on PowerFlower objects are done.
	 * All active objects in the PowerFlower framework are cleared on finalization.
	 * Once finalized the framework can not be re-initialized.
	 * @return \c true on success, \c false on failure.
	 */
	static bool Finalize(void);

	/**
	 * Checks if the PowerFlower framework has been finalized.
	 * @return \c true if finalized, \c false if not.
	 */
	static bool IsFinalized(void);

	// LIFECYCLE
	PowerFlower(void);
	~PowerFlower(void);

	// OPERATIONS
	void Clear(void);
	bool ReadPowerSystem(std::string& rSourceName, PowerSystemExt::Interface& rInterface);
	bool ReadPowerSystemFromMatPowerFile(std::string& rSourceName);
	bool ReadPowerSystemFromOptions(void);
	bool WritePowerSystemToString(std::string& rString); // :TODO: streams?
	bool PowerFlow(void) const;

	bool SolvePowerFlowTest(void) const;
	bool ContingencyAnalysis(void) const;



//	void Test(void);



private:

	bool GetContingencyAnalysisOptions(int& rInitialSolutionType, int& rPrecondioningType) const;
	NONLINEARSOLVER_NAMESPACE_NAME::Preconditioner* CreatePreconditionerFromOptions(void) const;
	bool SolvePowerFlowProblem(PowerFlowProblem& rProblem, VoltageVector* pInitialSolution, NONLINEARSOLVER_NAMESPACE_NAME::NonLinearSolver* pSolver, NONLINEARSOLVER_NAMESPACE_NAME::Preconditioner* pPreconditioner, NONLINEARSOLVER_NAMESPACE_NAME::ForcingTerms* pForcingTerms, SolveResult& rSolveResult) const;

	typedef std::list<PowerFlower*> ObjectListType;	///< Type of the list of active objects that require PETSc for destruction.
	static ObjectListType msObjectList;				///< List of active objects that require PETSc for destruction.
	static LogEvents msLogEvents;
	static const std::string msPetscOptionFile;
	static const int msPetscOptionMaxLength = 64;			///< Maximum number of characters in a command line option string.
	static const std::string msPetscOptionPrecoMatrixType;	///< Preconditioner matrix type option identifier.
	static const std::string msPetscOptionCAStartType;		///< Contingency analysis start type option identifier.
	static const std::string msPetscOptionCAPrecoType;		///< Contingency analysis preconditioning type option identifier.

	std::string mFilename;
	std::string mPrecoMatrixType;
	std::string mForcingTermsType;
	PowerSystemExt* mpPowerSystem;					///< PowerSystem object.
};

POWERFLOWER_NAMESPACE_END

#endif // PowerFlower_PowerFlower_h
