using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Txt2Bib.Records;
using System.Windows;
using System.Runtime.CompilerServices;
using System.CodeDom;

namespace Txt2Bib
{
    /// <summary>
    /// Converting entries from text file to BibTeX format
    /// </summary>
    public class Text2Bib
    {
        private readonly string[] _citTypes = { "J", "B", "C", "P" };
        
        /// <summary>
        /// Generate single .bib file from input text files
        /// </summary>
        /// <param name="filenames"></param>
        /// <returns></returns>
        public string Generate(string filenames)
        {
            var paths = filenames.Trim().Split('\n');
            var output = "";

            foreach (var path in paths)
            {
                output += CreateBibTeX(path);
            }

            return output;
        }
        /// <summary>
        /// Create a BibTeX string from an input file path
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public string CreateBibTeX(string path)
        {
            using var reader = File.OpenText(path);
            byte[] contentBytes = File.ReadAllBytes(path);
            var content = Encoding.Latin1.GetString(contentBytes);

            IEnumerable<string> entries = new List<string>();
            try
            {
                entries = content.Split('%').ToList().Select(entry => Process(entry));
            }
            catch (Exception)
            {
                throw;
            }

            var bibtex = "";
            foreach (var entry in entries)
            {
                bibtex += entry;
            }

            return bibtex;
        }
        /// <summary>
        /// Creates a bib entry from source text 
        /// </summary>
        /// <remarks>Handle exception</remarks>
        /// <param name="entryFromTxt"></param>
        /// <returns></returns>
        /// <exception cref="Exception">Invalid citation type for this entry</exception>
        public string Process(string entryFromTxt)
        {
            var lines = entryFromTxt.Trim().Replace("\r", string.Empty).Split("\n");
            var type = lines.First().Trim();

            if (!IsValidEntry(type)) throw new Exception($"Invalid entry type '{type}'");

            string citation;
            try
            {
                citation = type switch
                {
                    "J" => new Article().Convert(lines),
                    "B" => new Book().Convert(lines),
                    "C" => new Chapter().Convert(lines),
                    "P" => new Proceedings().Convert(lines),
                    _ => ""
                };
            }
            catch (Exception)
            {
                throw new Exception("Faulty string in " + entryFromTxt);
            }

            return citation;
        }
        /// <summary>
        /// Validate txt entry based
        /// on citation types
        /// </summary>
        /// <param name="entry"></param>
        protected bool IsValidEntry(string entryType)
        {
            return _citTypes.Contains(entryType);
        }
        /// <summary>
        /// TODO: How to determine correct encoding of text file??
        /// </summary>
        /// <param name="reader">The stream reader for the file</param>
        /// <returns></returns>
        private Encoding GuessEncoding(StreamReader reader)
        {
            var cp = "UTF-8";
            return Encoding.GetEncoding(cp);
        }
    }
}