using System;
using System.IO;
using Volpe.Cafe.IO.DSV;

namespace Volpe.Cafe.IO.TSV
{
    /// <summary>
    /// Provides static methods for the creation and opening of a tab-separated values (TSV) file.
    /// </summary>
    /// <remarks>
    /// The processing of TSV files (via the <see cref="TsvReader"/> and the <see cref="TsvWriter"/> classes) follows
    /// the RFC 4180 specification for the CSV file format (as outlined here: https://www.rfc-editor.org/rfc/rfc4180),
    /// but applicable to TSV files. In particular, the TSV classes adapt the specifics related to the treatment of the
    /// delimiter character (i.e., the tab <c>'\t'</c>), the escape character (i.e., the double quote <c>'"'</c>), and
    /// the various new line characters or string (CR or <c>'\r'</c>, LF or <c>'\n'</c>, CRLF or <c>"\r\n"</c>).
    /// </remarks>
    [Serializable]
    public static class TsvFile
    {
        /// <summary>
        /// Defines a character used for delimiting the columns in a TSV file.
        /// </summary>
        public const char Delimiter = '\t';

        /// <summary>
        /// Opens a TSV file at the specified <paramref name="path"/> for writing. If the file exists, it will be
        /// overwritten; otherwise, a new file will be created. The specified <paramref name="headers"/> will be
        /// written to the file upon successful opening.
        /// </summary>
        /// <param name="path">The complete file path to write to.</param>
        /// <param name="headers">An array of column headers to write to the TSV file.</param>
        /// <returns>A <see cref="TsvWriter"/> instance to use for writing the TSV file.</returns>
        /// <inheritdoc cref="TsvWriter(string, string[])" path="/exception"/>
        public static TsvWriter OpenWrite(string path, string[] headers)
        {
            ThrowHelper.ThrowIfHeadersNotValid(headers);
            return new TsvWriter(path, headers);
        }

        /// <summary>
        /// Opens an existing TSV file at the specified <paramref name="path"/> for writing. If the file exists, it
        /// will be appended to; otherwise, an exception will be thrown.
        /// </summary>
        /// <param name="path">The complete file path to write to.</param>
        /// <returns>A <see cref="TsvWriter"/> instance to use for writing the TSV file.</returns>
        /// <exception cref="FileNotFoundException">The file cannot be found.</exception>
        /// <inheritdoc cref="StreamWriter(string, bool)" path="/exception"/>
        public static TsvWriter OpenAppend(string path)
        {
            ThrowHelper.ThrowIfFileNotFound(path);
            return new TsvWriter(path, null);
        }

        /// <summary>
        /// Opens a TSV file at the specified <paramref name="path"/> for reading.
        /// </summary>
        /// <param name="path">The complete file path to read.</param>
        /// <returns>A <see cref="TsvReader"/> instance to use for reading the TSV file.</returns>
        /// <inheritdoc cref="TsvReader(string)" path="/exception"/>
        public static TsvReader OpenRead(string path)
        {
            return new TsvReader(path);
        }

    }
}
