﻿namespace CsvBuilder
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Reflection;
    using System.Text;

    /// <summary>
    /// CsvBuilder class can build csv file by collection of any items.
    /// </summary>
    public class CsvBuilder<T> : AbstractCsvBuilder<T>
    {

        /// <summary>
        /// Initializes a new instance of the <see cref="CsvBuilder" /> class.
        /// </summary>
        /// <param name="characterSeparator">Determine the character separator.</param>
        /// <param name="initialIdentation">The initial indentation. Can be used to construct more complex csv hierarchies. </param>
        /// <param name="includeHeaders">If true the headers name will be included, otherwise they are skipped.</param>
        /// <param name="getPropertiesNamesDelegate">The get property name delegate. Used to extract the name of the property or some attribute</param>
        public CsvBuilder(
            char characterSeparator,
            int initialIdentation = 0,
            bool includeHeaders = true,
            Func<PropertyInfo, string> getPropertiesNamesDelegate = null)
            : this(characterSeparator.ToString(), initialIdentation, includeHeaders, getPropertiesNamesDelegate)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CsvBuilder" /> class.
        /// </summary>
        /// <param name="characterSeparator">Determine the character separator.</param>
        /// <param name="initialIdentation">The initial indentation. Can be used to construct more complex csv hierarchies. </param>
        /// <param name="includeHeaders">If true the headers name will be included, otherwise they are skipped.</param>
        /// <param name="getPropertiesNamesDelegate">The get property name delegate. Used to extract the name of the property or some attribute</param>
         public CsvBuilder(
            string characterSeparator = ", ",
            int initialIdentation = 0,
            bool includeHeaders = true,
            Func<PropertyInfo, string> getPropertiesNamesDelegate = null)
             :base(characterSeparator, initialIdentation, includeHeaders, getPropertiesNamesDelegate)
        {
        }

        protected override IEnumerable<PropertyInfo> GetProperties()
        {
            IEnumerable<PropertyInfo> properties = typeof(T)
                .GetProperties()
                .Where(prop => prop.GetCustomAttribute<CsvIgnoreAttribute>() == null);

            return properties;
        }
    }
}
