#ifndef WORKSHEET_H
#define WORKSHEET_H

#include <string>
#include <vector>
#include <map>

namespace Libexcel {

	class Format;
	class Parser;
	class WorksheetImpl;

	// Class for generating Excel spreadsheets

	class Worksheet  
	{
	public:   

		enum Paper {PAPER_DEFAULT              = 0, 
					PAPER_LETTER               = 1,   // 8 1/2 x 11 in 
					PAPER_LETTERSMALL          = 2,   // 8 1/2 x 11 in
					PAPER_TABLOID              = 3,   // 11 x 17 in 
					PAPER_LEDGER               = 4,   // 17 x 11 in  
					PAPER_LEGAL                = 5,   // 8 1/2 x 14 in   
					PAPER_STATEMENT            = 6,   // 5 1/2 x 8 1/2 in
					PAPER_EXECUTIVE            = 7,   // 7 1/4 x 10 1/2 in
					PAPER_A3                   = 8,   // 297 x 420 mm      
					PAPER_A4                   = 9,   // 210 x 297 mm      
					PAPER_A4SMALL              = 10,  // 210 x 297 mm  
					PAPER_A5                   = 11,  // 148 x 210 mm       
					PAPER_B4                   = 12,  // 250 x 354 mm
					PAPER_B5                   = 13,  // 182 x 257 mm       
					PAPER_FOLIO                = 14,  // 8 1/2 x 13 in    
					PAPER_QUATRO               = 15,  // 215 x 275 mm   
					PAPER_10x14                = 16,  // 10x14 in    
					PAPER_10x17                = 17,  // 11x17 in
					PAPER_NOTE                 = 18,  // 8 1/2 x 11 in
					PAPER_ENVELOPE_9           = 19,  // 3 7/8 x 8 7/8
					PAPER_ENVELOPE_10          = 20,  // 4 1/8 x 9 1/2
					PAPER_ENVELOPE_11          = 21,  // 4 1/2 x 10 3/8
					PAPER_ENVELOPE_12          = 22,  // 4 3/4 x 11
					PAPER_ENVELOPE_14          = 23,  // 5 x 11 1/2
					PAPER_C_SIZE               = 24,  
					PAPER_D_SIZE               = 25,
					PAPER_E_SIZE               = 26,
					PAPER_ENVELOPE_DL          = 27,  // 110 x 220 mm 
					PAPER_ENVELOPE_C3          = 28,  // 324 x 458 mm
					PAPER_ENVELOPE_C4          = 29,  // 229 x 324 mm
					PAPER_ENVELOPE_C5          = 30,  // 162 x 229 mm
					PAPER_ENVELOPE_C6          = 31,  // 114 x 162 mm
					PAPER_ENVELOPE_C65         = 32,  // 114 x 229 mm
					PAPER_ENVELOPE_B4          = 33,  // 250 x 353 mm
					PAPER_ENVELOPE_B5          = 34,  // 176 x 250 mm
					PAPER_ENVELOPE_B6          = 35,  // 176 x 125 mm
					PAPER_ENVELOPE_ITALY       = 36,  // 110 x 230 mm
					PAPER_MONARCH              = 37,  // 3.875 x 7.5 in
					PAPER_ENVELOPE             = 38,  // 3 5/8 x 6 1/2 in 
					PAPER_FANFOLD              = 39,  // 14 7/8 x 11 in
					PAPER_GERMAN_STD_FANFOLD   = 40,  // 8 1/2 x 12 in
					PAPER_GERMAN_LEGAL_FANFOLD = 41}; // 8 1/2 x 13 in

	    
		// General writing

		void write(std::wstring cell, std::wstring token, Format* format = NULL);                             // write value to cell (A1)
		void write(int row, int col, std::wstring token, Format* format = NULL);                              // write value to cell (0,0)

		void write(std::wstring cell, double token, Format* format = NULL); 		                          // write numeric value (A1)	
		void write(int row, int col, double token, Format* format = NULL);                                    // write numeric value (0,0)

		void writeRow(std::wstring cell, std::vector<std::vector<std::wstring> > val, Format* format = NULL); // write an array of values as a row (A1)
		void writeRow(int row, int col, std::vector<std::vector<std::wstring> > val, Format* format = NULL);  // write an array of values as a row (0,0) 

		void writeCol(std::wstring cell, std::vector<std::wstring> val, Format* format = NULL);               // write an array of values as a column (A1)
		void writeCol(int row, int col, std::vector<std::wstring> val, Format* format = NULL);                // write an array of values as a column (0,0)

		// Typed writing

		void writeBlank(int row, int col, Format* format = NULL);											  // write a blank cell 
		void writeNumber(int row, int col, double num, Format* format = NULL);								  // write a number
		void writeString(int row, int col, std::wstring str, Format* format = NULL);                          // write a string
		void writeFormula(int row, int col, std::wstring formula, Format* format = NULL);		              // write a formula
		void writeUrl(int row, int col, std::wstring url, std::wstring str = L"",  Format* format = NULL);    // write an url
		void writeDate(int row, int col, std::wstring date, Format* format = NULL);                           // write a date 
		void writeTime(int row, int col, std::wstring time, Format* format = NULL);                           // write a time
		void writeDateTime(int row, int col, std::wstring datetime, Format* format = NULL);                   // write date and time
		void writeBitmap(int row, int col, std::string filename);                                             // insert bitmap image in a worksheet		
	
		// Formatting & appearance
	   
		void setColumn(int firstcol, int lastcol, int width, Format* format = NULL, bool hidden = false);     // set the width, format and hidden flag for column(s)
		void setRow(int row, int height = -1, Format* format = NULL, bool hidden = false);                    // set the height, format and hidden flag for a row
		void setMerge(int first_row, int first_col, int last_row, int last_col);                              // set a merged cell range      		
		void showScreenGridlines(bool show = true);                                                           // show/hide gridlines on the worksheet   
		void setZoom(int scale = 100);                                                                        // set the worksheet zoom factor

		// Actions

		void activate(bool b = true);                                                                         // set active this worksheet (displayed when the workbook is opened)		
		void select(bool b = true);                                                                           // select this worksheet (has highlighted tab)
		void setFirstSheet();                                                                                 // set this worksheet as the first visible sheet		
		void protect(const std::string& password);                                                            // protect this worksheet 
		void setSelection(int first_row, int first_col, int last_row, int last_col);                          // set selected cells in this worksheet
		
		// Page configuration
		
		void setPortrait();                                                                                   // set portrait page orientation
		void setLandscape();                                                                                  // set landscape page orientation
		void setPaper(Paper size = PAPER_DEFAULT);                                                            // set paper size

		void setHeader(std::string str, double margin = 0.50);                                                // set page header caption
		void setHeader(std::wstring str, double margin = 0.50);                                               // set page header caption (unicode)

		void setFooter(std::string str, double margin = 0.50);                                                // set page footer caption
		void setFooter(std::wstring str, double margin = 0.50);                                               // set page footer caption (unicode)

		void centerHorizontally(bool center = true);                                                          // center page horinzontally
		void centerVertically(bool center = true);                                                            // center page vertically 

		void setMargins(double margin);                                                                       // set all page margins to same value (inches)
		void setMarginLeft(double margin = 0.75);                                                             // set left margin (inches)  
		void setMarginRight(double margin = 0.75);                                                            // set right margin (inches)
		void setMarginTop(double margin = 1.00);                                                              // set top margin (inches)
		void setMarginBottom(double margin = 1.00);                                                           // set bottom margin (inches)
		
		void showGridlines(bool show = true);                                                                 // show/hide gridlines on the printed page
        
		void printRowColHeaders(bool print = true);                                                           // set the option to print the row and column headers on the printed page	
		void setPrintScale(int scale = 100);                                                                  // set the scale factor for the printed page

		// Utils

		const std::wstring& name() const;	                                                                  // get worksheet name
							
		WorksheetImpl* getImpl() { return m_impl; }                                                           // for internal use only

	private:
		friend class WorkbookImpl;
		Worksheet(int BIFF_version_, const std::wstring& name_,
													int index_, int& activesheet_,
													int& firstsheet_, int& str_total_,
													int& str_unique_, std::map<std::string, int>& str_table_,
													Format* url_format_, Format* date_format_, Format* time_format_, Format* datetime_format_, Parser* parser_);
		~Worksheet();    
		WorksheetImpl* m_impl;	
	};
}

#endif
