using System;
using System.Collections.Generic;
using System.Text;

using iTextSharp.text.pdf;

namespace PDFAnnotList
{
    /// <summary>
    /// PDFファイルの注釈を読み込みます。
    /// </summary>
    class PDFAnnotationReader
    {
        /// <summary>
        /// PDFファイルを読み込み注釈を取得します。
        /// </summary>
        /// <param name="filePath">PDFファイルのパス。</param>
        /// <returns>Annotationオブジェクトのリスト。</returns>
        public ICollection<Annotation> Read(string filePath)
        {
            List<Annotation> result = new List<Annotation>();

            PdfReader reader = new PdfReader(new RandomAccessFileOrArray(filePath), null);

            for (int i = 1; i <= reader.NumberOfPages; i++)
            {
                PdfDictionary pageDic = reader.GetPageN(i);
                result.AddRange(ReadPage(pageDic, i));
            }

            return result;
        }

        /// <summary>
        /// ページを読み込み、ページ内の注釈を取得します。
        /// </summary>
        /// <param name="pageDic">ページのPdfDictionary。</param>
        /// <param name="pageNumber">ページ番号。</param>
        /// <returns>ページ内に含まれる注釈のリスト。</returns>
        private static List<Annotation> ReadPage(PdfDictionary pageDic, int pageNumber)
        {
            List<Annotation> result = new List<Annotation>();

            PdfArray annotArray = (PdfArray)PdfReader.GetPdfObject(pageDic.Get(PdfName.ANNOTS));

            if (annotArray == null)
            {
                return result;
            }

            foreach (PdfIndirectReference annot in annotArray.ArrayList)
            {
                PdfDictionary annotDic = (PdfDictionary)PdfReader.GetPdfObject(annot);
                PdfName subType = (PdfName)annotDic.Get(PdfName.SUBTYPE);
                if (AcceptAnnotation(subType))
                {
                    result.Add(new Annotation(annotDic, pageNumber));
                }
            }

            return result;
        }

        /// <summary>
        /// 処理対象の注釈かどうか取得します。
        /// </summary>
        /// <param name="annotSubType">注釈のサブタイプ。</param>
        /// <returns>処理対象の注釈はtrue、処理対象外の注釈はfalse。</returns>
        private static bool AcceptAnnotation(PdfName annotSubType)
        {
            if (annotSubType == PdfName.TEXT)       return true;
            if (annotSubType == PdfName.HIGHLIGHT)  return true;
            if (annotSubType == PdfName.UNDERLINE)  return true;
            if (annotSubType == PdfName.FREETEXT)   return true;
            if (annotSubType == PdfName.LINE)       return true;
            if (annotSubType == PdfName.SQUARE)     return true;
            if (annotSubType == PdfName.CIRCLE)     return true;
            if (annotSubType == PdfName.POLYGON)    return true;
            if (annotSubType == PdfName.POLYLINE)   return true;
            if (annotSubType == PdfName.SQUIGGLY)   return true;
            if (annotSubType == PdfName.STRIKEOUT)  return true;
            if (annotSubType == PdfName.STAMP)      return true;
            if (annotSubType == PdfName.INK)        return true;

            return false;
        }
    }
}
