using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace C1.Silverlight.FlexGridExcel
{
    /// <summary>
    /// Represents a MS Excel spreadsheet.
    /// </summary>
    public class XLSheet
    {
        //-------------------------------------------------------------------------
        #region ** fields

        Dictionary<int, XLRow> _rows;
        Dictionary<int, XLColumn> _columns;
        int _rowCount;
        int _colCount;
        bool _summaryBelow;

        #endregion

        //-------------------------------------------------------------------------
        #region ** ctor

        /// <summary>
        /// Initializes a new instance of an <see cref="XLSheet"/>.
        /// </summary>
        /// <param name="document">Document to load the sheet from.</param>
        public XLSheet(XDocument document)
        {
            Document = document;
            // read columns
            _columns = new Dictionary<int, XLColumn>();
            _colCount = 0;
            XElement columnData = document.Descendants(XLWorkbook.SheetNS + XLConstants.COLUMNS).First();
            foreach (var element in columnData.Descendants(XLWorkbook.SheetNS + XLConstants.COLUMN))
            {
                _columns[_colCount++] = new XLColumn(element);
            }
            // read rows
            XElement sheetData = document.Descendants(XLWorkbook.SheetNS + XLConstants.SHEET_DATA).First();
            _rows = new Dictionary<int, XLRow>();
            _rowCount = 0;
            foreach (var element in sheetData.Descendants(XLWorkbook.SheetNS + XLConstants.ROW))
            {
                XLRow row =  new XLRow(element);
                _rows[_rowCount++] = row;
            }
        }

        #endregion

        //-------------------------------------------------------------------------
        #region ** object model

        /// <summary>
        /// Gets or sets a value that indicates where group rows should be displayed with
        /// respect to the data.
        /// </summary>
        /// <value><c>True</c> if summary appears below; otherwise, <c>false</c>.</value>
        public bool SummaryBelow
        {
            get { return _summaryBelow; }
            set
            {
                _summaryBelow = value;
                var outlineElement = new XElement(XLWorkbook.SheetNS + XLConstants.OUTLINE_PROPERTIES);
                outlineElement.SetAttributeValue(XLConstants.SUMMARY_BELOW, value ? 1 : 0);
                XElement sheetProperties = Document.Descendants(XLWorkbook.SheetNS + XLConstants.SHEET_PROPERTIES).First();
                sheetProperties.Add(outlineElement);
            }
        }
        /// <summary>
        /// Gets a <see cref="XDocument"/> that contains the sheet definition.
        /// </summary>
        public XDocument Document { get; private set; }
        /// <summary>
        /// Gets the columns belonging to this sheet.
        /// </summary>
        /// <value>The columns.</value>
        public ICollection<XLColumn> Columns
        {
            get { return _columns.Values; }
        }
        /// <summary>
        /// Gets the rows belonging to this sheet.
        /// </summary>
        /// <value>The rows.</value>
        public ICollection<XLRow> Rows
        {
            get { return _rows.Values; }
        }
        /// <summary>
        /// Creates a new row and adds it to the current spreadsheet.
        /// </summary>
        /// <returns>The new row.</returns>
        public XLRow AddRow()
        {
            var newRow = new XLRow(++_rowCount);
            XElement sheetData = Document.Descendants(XLWorkbook.SheetNS + XLConstants.SHEET_DATA).First();
            sheetData.Add(newRow.Element);
            _rows[_rows.Count] = newRow;
            return newRow;
        }
        /// <summary>
        /// Creates a new row and adds it to the current spreadsheet.
        /// </summary>
        /// <param name="outlineLevel">The outline level of the row.</param>
        /// <returns>The new row.</returns>
        public XLRow AddRow(int outlineLevel)
        {
            var newRow = AddRow();
            newRow.OutlineLevel = outlineLevel;
            return newRow;
        }
        /// <summary>
        /// Creates a new column and adds it to the current spreadsheet.
        /// </summary>
        /// <returns>The new column.</returns>
        public XLColumn AddColumn()
        {
            var newCol = new XLColumn(++_colCount);
            XElement columnData = Document.Descendants(XLWorkbook.SheetNS + XLConstants.COLUMNS).First();
            columnData.Add(newCol.Element);
            _columns[_columns.Count] = newCol ;
            return newCol;
        }
        /// <summary>
        /// Creates a new column and adds it to the current spreadsheet.
        /// </summary>
        /// <param name="width">The width of the column.</param>
        /// <returns>The new column.</returns>
        public XLColumn AddColumn(double width)
        {
            var newCol = AddColumn();
            newCol.Width = width;
            return newCol;
        }

        #endregion
    }
}
