using namespace System;
using namespace System::IO;
using namespace System::Text;
using namespace System::Collections::Generic;
using namespace System::Text::RegularExpressions;

#include "Cellule.h"
#include "Evaluator.h"
#include "Sommet.h"

namespace CLITableur
{
    /// <summary>
    /// Feuille de calcul
    /// </summary>
    public ref class Feuille
    {        
	public: 
		/// <summary>
		/// Fonction appellée quand une cellule est mise à jour
		///	</summary>
		delegate void del_cellUpdated(int col, int row, String^ value);        

		/// <summary>
		/// Déclenché lorsqu'une cellule est mise à jour (calculée)
		///	</summary>
        event del_cellUpdated^ OnCellUpdated;

		/// <summary>
		/// Fonction appelée lorsque le style est modifié
		///	</summary>
		delegate void del_cellStyleUpdated(int col, int row);        

		/// <summary>
		/// Déclenché lorsque le style est modifié
		///	</summary>
        event del_cellStyleUpdated^ OnCellStyleUpdated;



        // taille de la feuille
		
		/// <summary>
		/// Nombre de lignes max
		///	</summary>
        const static int ROWS = 100;

		/// <summary>
		/// Nombre de colonnes max
		///	</summary>
        const static int COLS = 52;

	private: 
		int rows;
		int cols;

		/// <summary>
		/// Cellules composant la feuille de calcul
		///	</summary>
		array<Cellule^,2>^ cells;
        
	public: 
		/// <summary>
		/// Accès indexé aux cellules
		///	</summary>
		Cellule^ Cells(int col,int row);		

		/// <summary>
		/// Constructeur
		///	</summary>
		Feuille();
                
	private:
		/// <summary>
		/// Evalue le contenu d'une cellule
		///	</summary>
		String^ evalue(Cellule^ cell, int col, int row);        

		/// <summary>
		/// Appelé pour capturer la valeur d'une cellule
		///	</summary>
        void ev_OnGetCellValue(String^ name, double & value);        	

		/// <summary>
		/// Identifie les références des cellules contenues dans une plage
		///	</summary>
		array<Cellule^>^ GetRange(String^ range);

		/// <summary>
		/// Instance d'évaluateur
		///	</summary>
		Evaluator^ ev;

		/// <summary>
		/// Erreurs
		///	</summary>
		StringBuilder^ errors;

	public:
		/// <summary>
		/// Recalcule la feuille après détermination du plan
		///	</summary>
		void recalc();     
        
	private:
		/// <summary>
		/// Chemin et nom de fichier (membre privé)
		///	</summary>
		String^ filename;

		/// <summary>
		/// Nom du document (membre privé)
		///	</summary>
		String^ fileshortname;

		/// <summary>
		/// Indique si une modification a eu lieu depuis la dernière sauvegarde (membre privé)
		///	</summary>
		bool isModified;

		/// <summary>
		/// Enregistre le document vers le fichier filename
		///	</summary>
		void SaveToFilename();		

		/// <summary>
		/// Produit un flux XSLX
		///	</summary>
		String^ GetExcelStream();

	public:
		/// <summary>
		/// Constructeur applicatif
		///	</summary>
		void Init();

		/// <summary>
		/// Indique si le document a été modifié depuis la dernière sauvegarde
		///	</summary>
		property bool IsModified
		{
			bool get() 
			{ 
				return isModified; 
			}
		}

		/// <summary>
		/// Obtient ou définit le nom/chemin du document
		///	</summary>
		property String^ Filename
		{
			String^ get()
			{
				return filename;
			}

			void set(String^ value)
			{
				this->filename = value;
				
	            FileInfo^ f = gcnew FileInfo(filename);
				this->fileshortname = f->Name;
			}
		}

		/// <summary>
		/// Obtient le nom du document
		///	</summary>
		property String^ Fileshortname
		{
			String^ get()
			{
				return fileshortname;
			}			
		}

		/// <summary>
		/// Enregistre le document
		///	</summary>
		void Save();

		/// <summary>
		/// Enregistre sous un autre nom
		///	</summary>
		void Save(String^ filename);


		/// <summary>
		/// Charge le document
		///	</summary>
		void Load(String^ filename);


		/// <summary>
		/// Enregistre une copie au format XLSX
		///	</summary>
		void SaveCopyExcel(String^ filename);
    };
}