using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;

namespace PDFAnnotList
{
    /// <summary>
    /// XMLプレッドシートとして書き込みます。
    /// </summary>
    class XmlSpreadsheetWriter
    {
        /// <summary>
        /// 注釈をXMLプレッドシートに書き込みます。
        /// </summary>
        /// <param name="filePath">書き込むファイルのパス。</param>
        /// <param name="annots">注釈。</param>
        public void Write(string filePath, IEnumerable<Annotation> annots)
        {
            StringBuilder xmlText = new StringBuilder();
            xmlText.Append(GetHeader());
            xmlText.Append(GetAnnotRows(annots));
            xmlText.Append(GetFooter());
            File.WriteAllText(filePath, xmlText.ToString(), Encoding.UTF8);
        }

        /// <summary>
        /// XMLスプレッドシートのヘッダーを取得します。
        /// </summary>
        /// <returns>XMLスプレッドシートのヘッダー。</returns>
        private string GetHeader()
        {
            return
@"<?xml version=""1.0""?>
<?mso-application progid=""Excel.Sheet""?>
<Workbook xmlns=""urn:schemas-microsoft-com:office:spreadsheet""
xmlns:x=""urn:schemas-microsoft-com:office:excel""
xmlns:ss=""urn:schemas-microsoft-com:office:spreadsheet"">
<Styles>
<Style ss:ID=""DateTimeFormat"">
<NumberFormat ss:Format=""yyyy/mm/dd\ hh:mm;@""/>
</Style>
<Style ss:ID=""TitleRow"">
<Font ss:Bold=""1"" ss:Size=""11"" />
</Style>
</Styles>

<Worksheet ss:Name=""Sheet1"">
<Table>
<Row>
<Cell ss:StyleID=""TitleRow""><Data ss:Type=""String"">Page</Data></Cell>
<Cell ss:StyleID=""TitleRow""><Data ss:Type=""String"">Author</Data></Cell>
<Cell ss:StyleID=""TitleRow""><Data ss:Type=""String"">Creation</Data></Cell>
<Cell ss:StyleID=""TitleRow""><Data ss:Type=""String"">Modified</Data></Cell>
<Cell ss:StyleID=""TitleRow""><Data ss:Type=""String"">Comment</Data></Cell>
</Row>
";
        }

        /// <summary>
        /// XMLプレッドシートの行を取得します。
        /// </summary>
        /// <param name="annots">行に対応する注釈。</param>
        private string GetAnnotRows(IEnumerable<Annotation> annots)
        {
            StringBuilder result = new StringBuilder();

            foreach (Annotation annot in annots)
            {
                result.AppendLine("<Row>");
                result.AppendLine(GetNumberCell(annot.PageNumber));
                result.AppendLine(GetStringCell(annot.Author));
                result.AppendLine(GetDateTimeCell(annot.CreationDate));
                result.AppendLine(GetDateTimeCell(annot.ModifiedDate));
                result.AppendLine(GetStringCell(annot.Contents));
                result.AppendLine("</Row>");
            }

            return result.ToString();
        }

        /// <summary>
        /// XMLスプレッドシートのフッターを取得します。
        /// </summary>
        /// <returns>XMLスプレッドシートのフッター。</returns>
        private string GetFooter()
        {
            return "</Table></Worksheet></Workbook>";
        }

        /// <summary>
        /// DateTime型セルのXMLノードを取得します。
        /// </summary>
        /// <param name="number">セルの値。</param>
        /// <returns>セルのXMLノード。</returns>
        private string GetDateTimeCell(DateTime date)
        {
            if (date == new DateTime(0))
            {
                return GetStringCell("");
            }

            string result = GetCellNode("DateTime", String.Format("{0:yyyy-MM-dd}T{0:HH:mm:ss.fff}", date));
            return result.Replace("<Cell>", "<Cell ss:StyleID=\"DateTimeFormat\">");
        }

        /// <summary>
        /// Number型セルのXMLノードを取得します。
        /// </summary>
        /// <param name="number">セルの値。</param>
        /// <returns>セルのXMLノード。</returns>
        private string GetNumberCell(int number)
        {
            return GetCellNode("Number", number.ToString());
        }

        /// <summary>
        /// String型セルのXMLノードを取得します。
        /// </summary>
        /// <param name="number">セルの値。</param>
        /// <returns>セルのXMLノード。</returns>
        private string GetStringCell(string str)
        {
            string cellValue = str.Replace("\r\n", "\n");
            cellValue = cellValue.Replace('\r', '\n');
            cellValue = cellValue.Replace("\n", "&#10;");
            cellValue = cellValue.Replace('\t', ' ');

            return GetCellNode("String", str);
        }

        /// <summary>
        /// セルのXMLノードを取得します。
        /// </summary>
        /// <param name="valueType">セルの型。</param>
        /// <param name="value">セルの値。</param>
        /// <returns>セルのXMLノード。</returns>
        private string GetCellNode(string type, string value)
        {
            StringBuilder result = new StringBuilder();
            result.Append("<Cell><Data ss:Type=\"").Append(type).Append("\">");
            result.Append(value);
            result.Append("</Data></Cell>");
            return result.ToString();
        }

    }
}
